This week, the exercises cover the basics of HTML, CSS, and JavaScript. We use Svelte, a modern web framework, for this course. So, the questions will show you how to do things within Svelte.
In Svelte, web pages are build up from reusable components that include all
HTML, CSS, and JavaScript functionality to make a single functional item.
Components are implemented in .svelte
files, which contain three
(optional) blocks of code:
<!--- JavaScript code --->
<script>
const world = 'world';
</script>
<!--- HTML markup --->
<p>Hello {world}!</p>
<!--- CSS markup --->
<style>
p {
font-weight: 600;
}
</style>
By putting all relevant code of a single component in one place, it becomes
easier to develop websites and reduces the chance of breaking something when
you make changes to a single component. Another big benefit of Svelte is that
it makes it easy to put values from your script onto a page. In the example
above, we printed the string in the variableworld
into the <p></p>
tags. Svelte will automatically
update the value in the <p></p>
tags when the value
of the variable changes.
For this exercise, you have to edit the file src/routes/week_5/exercises/ex_1.svelte
. Any changes you make to that file should show up below.
HTML has a lot of tags
you can use to build a web page. In this exercise, you will use the section header
tags. Add headers of all sizes in ex_1.svelte
's <div></div>
tag. Order the tags in decreasing size and give each tag the name Section x
, where the x
is the header's size.
For this exercise, you have to edit the file src/routes/week_5/exercises/ex_2.svelte
. Any changes you make to that file should show up below.
There are also several tags
that layout text. For example, tags that make paragraphs and lists. Within ex_2.svelte
's <div></div>
tag, add a paragraph saying
"The best visual channels ordered by Mackinlay's ranking:"
and an ordered list containing the items: Position, Length,
and Angle.
For this exercise, you have to edit the file src/routes/week_5/exercises/ex_3.svelte
. Any changes you make to that file should show up below.
You can also use tags
that format text. These tags are inline: they do not change where text is shown,
only how it is shown. Within ex_3.svelte
, use tags to
emphasize the word marks
, strike through the
word basic
, and make geometric elements
appear
bold.
Marks are basic geometric elements that depict items and links.
For this exercise, you have to edit the file src/routes/week_5/exercises/ex_4.svelte
. Any changes you make to that file should show up below.
The last tag we want to demonstrate, and one you will use a lot, is the <div></div>
-tag. It is used to group content together and describes how a page should
be layed out. Generally, <div></div>
-tags allow
you to apply styling rules to their content. Several approaches to page-layout
exist;
this article
provides a nice overview. You do not have to know how to build layouts by heart,
but understanding the approaches helps when you try to get your content at a specific
place on your page! This site already uses
Bootstrap, so you can use their classes in the exercises if you want, but you are not
required to.
By default, exercise components are centered horizontally on the page because
they are placed within a <div></div>
-tag
configured to act as a flex-row
. Consequently, individual tags
within the exercise components are shown side by side. If you want to show
tags below each other, you have to put them in a <div></div>
-tag.
Make the two messages in ex_4.svelte
appear below each other.
The first message!
The second message!
For this exercise, you have to edit the file src/routes/week_5/exercises/ex_5.svelte
. Any changes you make to that file should show up below.
To change how things look, you can use CSS. There are two ways to apply CSS rules, you can define them inline with the
HTML tags using the style
attribute:
<span style='color: red'></span>
or you can define rules for all DOM elements that match a CSS selector
in the <style></style>
-tags of a Svelte
component:
<style>
p {
color: red;
}
</style>
Usually, it is easiest to define styles within the <style></style>
-tags. However, the inline form can be very useful if the value you want to
apply depends on a value in your script because Svelte can not use JavaScript
values within the <style></style>
-tags!
Add a style element to ex_5.svelte
that changes the font and text
size, and sets the text color to steelblue. In addition, give the word
really
a different color from the other words.
I really like data visualisation!
For this exercise, you have to edit the file src/routes/week_5/exercises/ex_6.svelte
. Any changes you make to that file should show up below.
Svelte makes it easy to use JavaScript code in your components. In the following exercises, we briefly cover the basics of JavaScript. We recommend that you check out Eloquent JavaScript if you want more information because JavaScript has many funny corner cases!
Variables are a fundamental aspect of programming. They allow you to keep track of your program's state. In JavaScript, you can define two types of variables: constant variables that can not change value:
const my_variable = 10;
and mutable variables that can change value:
let my_variable = 10;
We recommend that you define all your variables as constant to start with.
Only make them mutable when it is needed. In old code, you may see variables
initialized with the var
keyword. This is a
sign that the code you are looking at is old and you should take care when using
it! Do not use the
var
keyword in code for this course.
Define a constant variable with your lucky number as value. Complete the message with the variable's value. Hint: see the hello-world example at the beginning!
My lucky number is
For this exercise, you have to edit the file src/routes/week_5/exercises/ex_7.svelte
. Any changes you make to that file should show up below.
Two data types that you will encouter a lot in this course are lists and objects. Lists contain a sequence of values that do not have to be of the same type. However, it is easier to work with lists that only include the same kind of item, i.e., only numbers or only strings. You can construct and access values in a list as follows:
const myList = [0, 1, 2, 3, 'a', 'b', null];
console.log(myList[0]);
console.log(myList[1]);
It is also possible to append or remove items from a list using the .push()
and
.pop()
member functions.
Objects contain properties, i.e., key-value pairs. We typically use them to represent a data table's row in this course. To construct an object, you can specify the key and value explicitly:
const student = { name: 'J. Doe', number: 243901};
// Two ways to access the properties:
console.log(student.name);
console.log(student['number']);
// Add properties by assigning to them
student.curriculum = 'Statistics';
Object destructuring provides another syntax to construct and retrieve values from an object. In this variant, the names of the variables are used as keys:
const name = 'J. Doe';
const number = 243901;
const student = { name, number };
Extracting specific properties from an object works very similar:
const { name } = student;
An important thing to realize is, although these variables were defined with const
, it is possible to change values within the list or properties of the
object. There is a fundamental difference in changing a list's or object's
content and assigning a different list or object to a variable! So, updating
values is allowed:
myList[4] = 4;
student.name = 'M. Doe';
But assigning different lists or objects is not when the variable is constant!
myList = ['a', 'new', 'list'];
student = {name: 'Not Allowed'};
Note that primitive types, such as numbers, are their content. So, you can not change the value of a constant variable that contains a number, but you can change the content of a list in a constant variable!
Create an object containing your name and a list of your favourite things. Show and fill in this message "My name is ... and these are some of my favourite things: ... ." in a paragraph. Hint: the list does not have to look good yet.
For this exercise, you have to edit the file src/routes/week_5/exercises/ex_8.svelte
. Any changes you make to that file should show up below.
Another fundamental aspect of programming are functions. There are two ways to define functions. The traditional approach:
function add(x, y) {
return x + y;
}
and a two inline variants:
const add = (x, y) => {
return x + y;
};
const add = (x, y) => x + y;
When you use brackets ({ }
) in the inline version, you have
to specify a return value explicitly. If you do not use brackets ({ }
), the value after the arrow (=>
) is returned automatically!
The inline variants are often useful for simple functions that modify or extract a value from the argument they are given. Often in cases where you do not have to give them a name. For larger functions, or functions that you use in multiple places, we recommend that you use the traditional syntax.
When you are using functions, it is important to understand where the function
will find the variables that you use. The places where a variable can be
accessed is called its scope. Scope always depends on where variables and functions are defined! For
example, in a Svelte component, variables that are defined directly in the
<script>
</script>
-tag have a global scope. They can be accessed by all functions defined in
the component. Variables that are defined in a function can only be accessed
within that function, or by functions that are defined within that function.
So, in this example, enabled
can be accessed within the add()
function, but x
and y
can not be accessed outside
the add function:
// enabled is global to the Svelte component
let enabled = true;
function add(x, y) {
// x and y are local to the add function
return enabled ? x + y : null;
}
Later in the course, you will see more complex
higher-order functions, i.e, functions that return functions. In those cases, the variables defined
in the outer function can be used in the inner function. For example, here we
defined a clamper()
function that takes a minimum
and maximum value and returns a function that clamps the number it is given to
the specified range:
function clamper(min, max) {
return (num) => Math.min(Math.max(num, min), max);
}
const clamp = clamper(-1, 1);
console.log(clamp(2));
In this example, min
and max
are local to clamper()
but they are accessible in the inline-function defined in clamper()
. Next week, we will cover d3.js, which uses this construction a lot.
Fortunately, using functions like these is a lot simpler than writing them!
So, it is ok if this example was confusing to you.
Define a function that computes the circumference of a sphere from a radius. Use your function to show and fill in this message "The circumference of a circle with radius ...m is ...m ." in a paragraph. Show the circumference up to 2 decimals!
For this exercise, you have to edit the file src/routes/week_5/exercises/ex_9.svelte
. Any changes you make to that file should show up below.
A big part of development in Svelte is combining multiple components to build a more complex component. Before you can use a component within another component, you first have to import it, which is done in the JavaScript part of a component:
import A from 'a.svelte'
Now, you can use the component just like an HTML tag in the markup part of the component. Svelte components should always be imported using a name that starts with a capital letter, otherwise it will be interpreted as an HTML tag and not a Svelte component when you use it!
JavaScript also has a slight variation of this importing syntax which is more often used with JavaScript files than with Svelte files:
import {a, b, c} from a.js
In this variant, which uses object destructuring, you do not import the full module defined in a.js
but just the
individual functions and variables that you want to use. You will see both variants
in this course, but remember, Svelte components should be imported without curly
braces and individual functions or variables from javascript files should be imported
with curly braces!
Import the components of Exercise 3 and 2 and use them inside a <div></div>
tag so that Exercise 3's component is above Exercise 2's component.
For this exercise, you have to edit the files src/routes/week_5/exercises/ex_10.svelte
and src/routes/week_5/exercises/_ex_10_child.svelte
. Any
changes you make to those file should show up below.
Having a clean data-flow throughout your application and component hierarchy
is essential for maintainability. Svelte provides several ways in which you
can pass along data between components. The easiest are component properties,
which allow you to pass data from a parent to a child. The properties of a
component are defined in the script tag using the export
keyword. Suppose we have a component B.svelte
with:
<script>
export let count = 0;
</script>
<p>{count}</p>
Now, in a parent component we can use component B
:
<script>
...
let myCountingVariable = 100;
</script>
<B count={myCountingVariable} />
Note how we passed the information within myCountingVariable
to the
child component! We can also use B without specifing a value for count
, then the default value as defined in B.svelte
is used. Svelte
has a couple of short-hand notions for this pattern, which can be confusing sometimes.
Check out all variations in the
documentation.
Define a component property called answer
in _ex_10_child.svelte
, import _ex_10_child.svelte
in ex_10.svelte
,
and use the child component with the value 42 as the answer
to life the universe and everything.
For this exercise, you have to edit the file src/routes/week_5/exercises/ex_11.svelte
. Any changes you make to that file should show up below.
Sometimes you want to change the markup of your component depending on a condition in the script. For instance, when you only want to show a tooltip when a user hovers over a component. Svelte makes it easy to do this with their if-else blocks:
{#if condition}
...
{:else}
...
{/if}
Here, the condition is a JavaScript statement that evaluates to true
or false
and the markup you want to show
in either case is put on the ...
.
Add an if-else block to ex_11.svelte
that says
You have clicked the button!
when you have clicked the button and You have to click the button! when
you have not clicked the button.
For this exercise, you have to edit the file src/routes/week_5/exercises/ex_12.svelte
. Any changes you make to that file should show up below.
Another common pattern you will encounter is displaying a list of similar items. You do not have to copy-pase and slightly change versions of the same code to do that. Instead, you should use Svelte's each-block, which allows you to create markup for every item in a list:
{#each mylist as item}
...
{/each}
Here, the body of the loop will be executed once for every item in the loop. Svelte will automatically update the page when the list changes. In some cases, you'll want svelte to know which items were removed or added. For instance, when using animations. Check out the documentation for more information on this.
Use an each block to make an unordered list of the soccer players in the list. Each item in the list should look like: Name (video)
For this exercise, you have to edit the file src/routes/week_5/exercises/ex_13.svelte
. Any changes you make to that file should show up below.
In custom data visualizations it is common that you want to change a data point's visual encoding when it becomes selected. An easy way to do this is to define a CSS class that overrides the attributes you want to change and assign that class when a data point becomes selected. Svelte supports assigning classes based on a condition in the component's script:
<p class:myClassName={condition} />
Define a class that changes the background of the button when it is assigned and assign it to only the last-clicked button. No button should have the class when no button has been clicked yet.