Web Developing Tutorials

Introduction

These tutorials will guide you through learning the web programming languages HTML, CSS, and JavaScript. In addition, you will get introduced to the JavaScript runtime engine Node JS, the JavaScript framework Vue, and the JavaScript real-time communication library Socket IO. It will also walk you through structuring your project code, using github as a version-control system, using the client-server messaging architecture and getting started with the backend code that is provided for your project.

After you have worked through the whole tutorial, please upload your project, including all files and folders as a .zip to Studium. The deadline is Monday, December 2, 2019.

These tutorials are created to promote learning in your own pace, so take your time to work through the tutorials and don't hesitate to play around. The designs are only an example and if you want to get a deeper understanding about website design, it is highly recommended that you start exploring the possibilities and limitations of the three programming languages.

It is always good to try around a little by yourself when you encounter a problem. However, if you do the tutorial during the lab hours, use your teaching assistants to get help when you are seriously stuck. Your teaching assistants are always happy to help you out ☺

Notes: Throughout these tutorials there are notes with tips or caveats. These are additional information that clarifies issues along the way. The notes have a yellow background.
There will be tasks that you should carry out by producing some code or by creating new files. The tasks come in blue boxes like this one.
Codeblock
                        
                            Programming code is presented in code blocks that look like this one. 
  Sometimes they contain snippets of code for you to use in the different tasks.
  Sometimes they are used to provide more general examples.
                        
                    

In the flowing text you will also see that some text is highlighted either to demonstrate a file path or a piece of code.

Web Programming

In order to build a beautiful looking and functional website you will have to be able to master some languages. But let us start by looking at what happens when you visit a website. The way most communication is handled over the internet is through client-server requests and responses. Figure depicts how this works. When you visit a website, the browser in your computer will initiate a request to a server for a document as outlined by a URL (Uniform Resource Locator). Usually, the server will run some form of server side scripts, which will read and write information from and to a database. The content that has been fetched by the server is then relayed back to the client computer in the form of a collection of HTML, CSS, and JavaScript documents (as well as images and fonts sometimes) which are written in client-side languages. This means that they are interpreted by your web browser in order to display the website that has now been downloaded, and is running on your computer. If you build a website with only static content, where you do not need to store information, then HTML, CSS, and JavaScript is all you need. There is no need for using server side scripts or a database.

Schematics of how communication over the internet makes visiting web sites possible
Schematics of how communication over the internet makes visiting web sites possible.
All browsers have their own way of interpreting the content, which means that sometimes you will run into problems getting your website to look the same on different platforms or browsers.

The three different languages that you are about to learn have all three very distinct roles within web design. HTML handles semantics; it is a mark-up language that structures information through so called elements. CSS is a styling language which takes care of design and you use this language to create your preferred layout of your website by styling the different HTML elements. JavaScript is a programming language which can manipulate HTML elements, thus adding dynamics and functionality to your website so that it does not contain just static text.

There also exist a variety of other libraries for different purposes. For the projects, we recommend you to start with provided code skeleton and use other libraries with caution, because every additional library adds to the complexity of the project. While libraries may make your life easier in some parts, they also disguise many design decisions in their internal code. So if you use a library, make sure you understand what it is doing and why. "The library suggested this design" will not be a valid argument in the final presentation.

We will also introduce you to a JavaScript framework called Vue. A software framework is designed as an abstraction from the original programming language to make programming more efficient (and often easier and safer). So Vue is not an entirely different language, it just builds upon JavaScript and provides some neat ways to structure, access and manipulate your webiste content.

The most important advantage of using these web languages is that their files are encoded as plain text. This means that it is a human readable code, and can for example be transferred and used without having to be compiled or packed into archives. It is (if it is well structured, of course) easy to share between members of a project, and is also suitable for some trial and error, since changes are directly visible when the page is reloaded.

Be aware that files that make up your website will be readable by anybody who wants to read it (for example, you can read the source code of this website by doing a right click and select "View page source"). Therefore it is vital to never put any sensitive information in your client-side code. For example, never store your own or your users' passwords within the website code.

Something that is important to grasp is that a website is constructed through what is called the DOM, the Document Object Model. All HTML elements that you define in your HTML document will be organized hierarchically in the DOM through a parent-child relationship. Some features will be inherited in child elements from parent elements. These features can then be manipulated in CSS or JavaScript. This might not make a lot of sense right now but it is important that you have heard the term DOM because we will get back to it later and it is a fundamental part of understanding how your code is interpreted by a browser.

Development Environment

No matter what language you are programming in, it's always important to have a good development environment. A good IDE (integrated development environment) should provide syntax highlighting, code completion, error checking and refactoring, among others. Of course you can use whatever IDE suits you best and sometimes you need to try a couple before you find one that fits your workflow. If you have worked with an IDE in another language before, it's worth checking out if they also have support for HTML, CSS and JavaScript. For example, if you have worked with PyCharm (for Python), IntelliJ (for Java), CLion (for C / C++) or another JetBrains IDE before, you should check out WebStorm. If you have worked with Eclipse before, you can keep using it for this course, because it comes with support for web development, too. Other IDEs worth checking out are Atom (developed by GitHub) and Brackets (developed by Adobe), which are both free and open-source projects.

Before you get started with the first part of the tutorial, pick an IDE and install it on your local machine.

Git

Your Task

Your first task is to get yourself and overview of this tutorial.

In total there will be five parts that prepare you with basic knowledge about Git, HTML, CSS, JavaScript, Vue and the project structure. This knowledge is necessary to participate in the programming part of your project.

During the labs, we will work on general code concepts where you create code that you can re-use in your projects later on: Filling out forms, listening to events, sending and receiving messages. However, while your projects are about creating customized burgers, the labs will guide you through building a website to order burgers from a predefined menu.

The labs will build upon each other, so in the end you will have a burger ordering page in HTML, styled with CSS with added functionality in JavaScript that is embedded in the project structure and uses the backend project code provided by the teachers.

But now, let's get started with git. By the end of this section, you should have your own git repository set up and made your first commit. If you already know how to use git, fork this repository and clone it to your system so you can push your progress with this labs to your own copy of this repository. You may then continue with section 2. If you don't know what forking and cloning means, don't worry - by the end of this section you will!

What is git and why shall we use it?

Git is a version-control system which means it is a system that allows you to track changes in (source) files. This is handy for two reasons: First, it allows multiple people to work on the same project and even the same files without getting in each other's way. Everyone works on their own copy of the project and whenever they make a change, they synchronize it with the online system. If two people worked on the same file, git will try to merge the changes automatically. If that fails, it will point you exactly to the place where it fails and provides you with an easy way of solving this merge conflict. However, it also makes your life easier when you work on your own, because if you happen to make changes that break some functionality of your project, you can easily switch back to earlier versions where your code was still working.

The name git (which was first invented for the source code of the Linux kernel) may stand for global information tracker or goddamn idiotic truckload of sh*t (depending on which mood you're in, according to Linus Torvald). Git is not the only version-control system out there, but one of the most popular ones (together with SVN). Even though SVN and git have substaintial differences and people usually have strong opinions about which one to use, we will not get into this debate in this course. And while the specific commands used by git and SVN differ and some of the functionality they (don't) support deviates too, you will still be able to transfer the main ideas and learn other version control systems much quicker once you're familiar with one of them. And yes, the project in this course may be small enough to handle without a version control system, but almost all developers in research and industry use one nowadays, so this skill will become useful in almost any job you will take on.

In this course, we will be working with github, which is one online platform that can host your projects. Again, github is only one of many choices and later on you may come accross other platforms, like Bitbucket.

GitHub is free to use for public and open source projects, so start by creating an account on the GitHub website. Even though their free account is great and sufficient for most projects, it only allows you have projects that are visible for anyone. If you want to be able to create private repositories, you can very easily apply for a student developer pack.

Installation

In order to be able to use git on your computer, it needs to be installed first.This website contains further instructions on how to install git on your operating system. To check if your installation works successfully, open a terminal (command line on Windows) and type git --version. If the installation is succesfull, you should get an output similar to git version 2.10.0.windows.1.

Forking and cloning

Git is mostly used to work collaboratively on a project. To do this, we clone a repository to our own computer. You can clone your own repositories, or someone else's repositories as long as they are public. You don't need to have permission for cloning a repository. Let's take the Linux repository as an example. If you would type git clone https://github.com/torvalds/linux.git on your command line, you would get the source files for the Linux kernel downloaded to your computer (don't actually do that, unless you have a lot of time and space on your computer - this repository is huge!). After you cloned a repository, you have a local copy of all the files on your computer. You can now change those files locally. However, you cannot push your changes back to the repository, because you do not have permission to contribute to Linus' repository. So getting a local copy of a repository via clone and receiving updates from the central repository via pull can be done without permissions, but contributing to a repository via push requires permissions.

If you made a change to your local copy and then pushed this change to the central repository, everyone else can now pull those changes into their local copy of the repository. This is great, because you (hopefully) made useful changes to the project that everyone can use. However, there are other cases in which your changes might be very specific and not useful to everyone. Let's say you made some great changes to the Linux kernel, but they are only helpful for a very specific use case, so the Linux community does not want to include them to their central repository. If you still want to publish your changes, you can make a fork of the Linux kernel repository:

A fork is a copy of a repository. Forking a repository allows you to freely experiment with changes without affecting the original project. Most commonly, forks are used to either propose changes to someone else's project or to use someone else's project as a starting point for your own idea.

A fork is exactly what we need for the labs. We have created some backend code for you to use during the last part of the lab on GitHub. As you will notice, this is a public repository, so you are able to see and clone it without being a collaborator. However, in this case, it does not make sense that you are all pushing your code into the same repository because you are not working on the labs together. Instead, you all need to create your own websites to pass the labs. For this purpose, you first need to create your own centralized copy of this repository.

On GitHub, navigate to the lab repository. Make sure you're logged in to your account. Click on the Fork button in the top right corner of the page. Now you have your own fork of the respository. If you click on the image / pixel graphic in the top right corner of your screen and then on Your repositories you should see a repository with the name 1md031_18_students and the note Forked from MaikePaetzel/1md031_18_students.

The next step is to clone the repository (which means to get a local copy of the central repository to your computer):
  • In your browser, click on My repositories and then on 1md032_18_students. Click on the green button localted towards the top right part that sais Clone or download and then copy the link you see there.
  • Open the terminal / command line on your computer.
  • Navigate to the folder you want to copy the repository to. You can change directories (cd in short) by typing cd target_dir. You can use pwd (on Linux and Mac) or cd (on Windows) to print the working directory to the command line so you can make sure you're in the right directory.
  • Once you are in the correct folder, type git clone and then paste the link to your repository. Press enter.
  • If your repository is private, you will now need to provide your username and password. If you have not made your repository private, it will just download the files.

Changing files

Now that you have a local copy of the respository on your computer, let's take a look at some useful commands when working with git:

git add
If you create a new file in your repository directory, it is not automatically added to your repository. Right now, it is just a local file on your computer. To add the file to your respository, type git add filename. Make sure you are in the correct (sub) folder where the file is located.
git commit
With this command, you commit a file to your local copy of the respository. It is not yet made available in the centralized version. Whenever you make a commit, a snapshot of the current state of your project is saved. This version receives a specific identifier. Using this identifier, you can always get back to a certain point in your repository. This is why it is so important to make frequent commits. Even if you have made only a small change, it doesn't harm to make a commit. The smaller the increments of your commits are, the easier it will be to get back to a desired version of your project later on. Of course you don't need to remember every version identifier. You can take a look in the git log to find a certain version. This is why all commits need a good commit message. bug fix, for example, is not a good commit message, because you don't know which bug was fixed. So even if you are the only one committing to a respository, make sure you have good commit messages. You can commit all changes with the command git commit -a -m "Commit message". If you only want to commit a specific file, exchange -a (for all) with the file name of the file you want to commit.
git push
This command pushes your changes to the central respository. You can either push every single commit to your central respository (recommended if you collaborate with others) or only push occasionally after several commits (which is useful if you are working offline for a while).
git pull
This fetches changes made to the central respository. Make sure you pull frequently if you're working on a project together with others. That way you can make sure to minimize merge conflicts and always work with the most up-to-date version of the project.
git status
This is a useful command to keep track of the status of your repository. It will tell, among others, if your repository is up-to-date and if you have changes that are not committed.

Your local Git identity

The first time you set up Git and before getting started to commit and push your own work, you need to make sure your Git identity is set. This is of importance since every Git commit you will do will use this information, and so collaborators can track who made which commit easier. The user.name and user.email is listed in git config --list. There are a number of ways of doing editing it, but these two commands below should do the trick, by replacing the yourgitusername and yourgitemail respectively:

git config --global user.name "yourgitusername"

git config --global user.email "yourgitemail@example.com"

Start by making sure you have your Git Identity set, see the section above.

In the main folder of the repository, you will see a file called checklist.md. Open this file. It contains a list of all the tasks you need to complete in order to pass the labs. The first item on the list reads: "Fork and clone the 1md032_18_students repository". Check the box for this item and save the file. Now commit your change (remember to use a relevant commit message!) and push it to the central repository.

Branches

Larger projects often face the challenge of multiple people working together on the same project and implementing different parts of the system at the same time. Often those implementations are not just small fixes but part of a lager set of changes, which might be ongoing over multiple days and frequently leaves the project in unstable or untested stages. You do not want to commit changes to the master branch that are potentially not working and thus keep the other developers from doing their tasks until you have fixed the issue. On the other hand, you might still want to push your changes so the collegues directly involved in this task can test your changes or contribute. To solve this dilemma, you can create different branches.

Initially, you are always on the master branch. To create a new branch called NewBranch, type git checkout –b "NewBranch". If you type git status you will see that you are still in the master branch. You switch to your new branch with the command git checkout NewBranch. You can get back to the master branch with the same command - just change NewBranch to master. Once you are on your NewBranch, you can commit and push as usual. The only difference is now that only your collegues who have also checked out the NewBranch will see your changes. Everyone who keeps working on the master branch will not be affected.

Once you finished working on your tasks and the project is in a stable stage, you want to apply all your changes to the master branch, too. You do this by merging your NewBranch into the master branch. Just type git merge NewBranch while you are in the master branch and it will merge all the changes.

HTML

After you have familiarized yourself with git, let's get started with HTML. After working through this part of the tutorial, your website should look something like this:
Screenshot of first task

Project Framework Setup

Before we create our first HTML file, we first need to take a look where to store our HTML files and how to access them. In your projects, you will develop an ordering system for special burgers. Even though you will mostly develop the front-end, you will need some information exchange between the different views. For example, if the customer orders a burger, the kitchen needs to get the information in a form that makes sense to them. Of course the customer and kitchen staff views are not on the same computer, so we need to have a message exchange system to bring the information from one computer to the other. This is handled by a server, which distributes messages between the different clients. Don't worry, we will provide you with the code for the message exchange, but in order to be able to use it later, we will start this tutorial by setting up the server and do all testing through it.

First, download and install the JavaScript runtime engine Node JS.
  1. Navigate to the 1md032_18_students folder in a command line tool.
  2. Type npm install and wait while magic is installing the necessary libraries, which are specified in the file package.json (Don't worry about the npm warning at the end: "No repository field").
  3. Now take a look at the folder structure of the project. What types of files are located in what folder? Be careful where you put your files while working through this tutorial, otherwise your html document will not find them.
  4. You should be good to go now: Type node app.js in the command line tool to start the server. You should see "Server is listening on port 3000" printed on the console.
  5. Use a web browser to check what is happening at http://localhost:3000/. You should see a white page that says "Hello World" in the top left corner.

Node.js works as a server on your own computer now. This is why you can go to a certain localhost port and see your website. We need the server in order to be able to realize the sending of information between the different views. For now, do not worry about the other files you see in the downloaded project. We will come back to them in the fourth part of this tutorial, where we introduce you to the messaging system.

Please keep in mind that your Node server is configured to use the public folder as its root folder. This means that even though our html files are located in the views folder we must enter the paths to our images, CSS, and JavaScript files (stored in the img, css, and js subfolders of public) as if the html files were actually located in public rather than in views.

Tags and Elements

HTML is what is called a mark-up language, which means that it is not run like an executable file, but rather interpreted as a structure in which the content should be placed. HTML is in this way similar to XML, but HTML has a more defined set of mark-up tags. A tag is a string enclosed within angle brackets (i.e., '<' and '>'). For example <h1> is a heading tag which defines a heading on the first level. Any tag that contains text or other tags will have a closing tag as well, for example </h1>. Once you have defined a starting and closing tag with content in-between, you have created an HTML element, for example <h1>A heading</h1>.

You structure the information on your website to be interpreted by machines, this in order to make it easier for, for example, search engines to interpret the content on your website, or to make it more accessible for people with disabilities. Browsers will provide some basic layout to the HTML elements which make it easier for people to view your content, but in reality, it is more aimed at structuring your content to make it interpretable for computers. This is very important to grasp, that is the reason why semantics are separated from design by using HTML for structure and CSS for design.

Basic HTML Template

When building your website, you will create it by using any tags defined by the HTML5 standard developed by the World Wide Web Consortium. When building a website it is of course up to you to decide what tags to use depending on your needs. However, there are some fundamental tags (or elements) that are required for all websites.

Below is the fundamental structure that you need in order to start building your website. Open your index.html file with an editor again and copy and paste the following code in that file. Don't forget to save the file and then open http://localhost:3000/ in your web browser. You will see a blank page (the "Hello World" is gone) but the title of the document should display in the title bar.
Basic structure of an HTML5 document
                        
                            <!DOCTYPE html>
                            <html lang="en">
                                <head>
                                    <title>Page title shown in window title</title>
                                    <meta charset="utf-8"/>
                                </head>
                                <body>

                                </body>
                            </html>
                        
                    
Throughout these labs we will first start to build a basic window for the customer to select and order burgers. Change the page title to something meaningful that represents the purpose of our website. Save the file and reload the page in your browser to make sure it has changed.
Regarding the website we will build in these labs, feel free to make it your own if you wish. You can use any content you would like to complete the task of building the website by swapping out images and text to make it more personal to you. Just make sure you use the same HTML tags.

What we see in the index.html file is a number of HTML elements nested within one another, this will make up the structure of the DOM. The document starts with a doctype declaration. This tag tells the browser how the document should be interpreted. There are different implementations of HTML, we will focus on HTML5. All code of the document must reside within the <html> tag. The document ends with the closing </html> tag.

The document is then divided into two parts: (1) the head and (2) the body. The head contains meta-data about the document and links to external files used to render the web page, as well as the title of the document which will be displayed in the window (or tab) title of the browser. The meta element is used to specify page description, keywords, author, and other meta-data. Here we have defined that character set UTF-8 will be used, which means that the document will be able to display non-latin characters (e.g., åäö). The body contains all HTML elements that should be displayed in the browser window. This is the main portion of your HTML document.

The file name "index.html" is a special name used by web servers. When a person visits a web site without specifying what file in particular they wish to visit, the web server will look for a file called "index" and return it if it exists. This is generally your website's first page (or home page) that a visitor should see when visiting your website.

Attributes

Elements can be modified by so called attributes, these are written within the elements opening tag and the attributes consists of an attribute name with a corresponding value assigned within double quotation marks. An example was when the character set was defined in the head of the document: <meta charset="utf-8"/>.

There are two special attributes that all HTML elements can have: id and class. An id is a unique identifier for an element. It is up to you what you call it (e.g, <p id="unique">), but you cannot use the same id more than once in one and the same HTML document. The class attribute is also up to you what to call, but many elements can have the same class. You can also provide an element with multiple classes separated by a blank space, e.g.: <span class="firstclass secondclass">.

The id and class are attributes you will use a lot when building your web site. We will get back to them later, and how useful they are when working with CSS and JavaScript to style and manipulate your elements.

So, to summarise how an element is defined, let's recap the anatomy of an HTML element.

The anatomy of an HTML element
The anatomy of an HTML element.
Elements can also be referred to as nodes. In fact, within the DOM, everything is considered a node. The entire HTML document is a document node; all HTML elements are element nodes; the content of an HTML element is a text node; the attributes within an HTML element are attribute nodes. The outer most element in an XML document is considered a root node, in the case of HTML, this is always the <html> tag.

Comments in HTML

To add comments to your HTML code (which you should do) you can use <!-- Your comment goes here -->. This is also very helpful when you wish to comment out code when you are debugging or trying out new designs.

Common HTML Elements

<h1>
Defines a heading. There are six levels of headings from <h1> to <h6>.
<p>
Is used to define a paragraph with flowing text.
<br />
This tag adds a line break.
<a>
This is an anchor tag that defines a link the user can click. E.g., <a href="http://www.google.com/>Click this to get to the Google website</a>.
<img>
Displays an image in the document. The image has some required attributes: href gives the path to your image and alt provides an alternate text for people with visual impairment. The path can either be locally within your file structure or from a source on the web. You can also provide a title attribute which will display a tooltip-like text when a user holds the mouse pointer over the image. E.g, <img src="path/to/image/image-name.jpg" alt="Sunset in Uppsala" title="Sunset">. Important to note here is that the <img> element does not require a closing tag since it does not contain any content.
<div>
This is a divider and is a generic block element (see the Block and In-line section). This is used to define parts of your website that is not a common semantic element of your website.
<span>
This is a spanner and is a generic in-line element (see the Block and In-line section). This is used to define parts of your website that is not a common semantic element of your website.
Your first task is to add a main headline like "Welcome to BurgerOnline", two smaller headlines, one for selecting burgers and one for providing some information about the customer (delivery address,...), and a small paragraph below each headline that describes the purpose of the section. Look back at the image above with the final website to get an idea how it should look like.
Here is the first line of code to get started:
Burger Pub
                        
                            <body>
                                <h1>Välkommen till BurgerOnline</h1>
                            </body>
                        
                    
Once you have saved the file, open it up in your web browser. What you will see is something that looks like a Word document. This is plain HTML which only has rudimentary layout and design provided by default from the browser.

Document Structure Elements

In HTML5, new semantic elements were added which tells the structure of the HTML document. Semantic elements have specific meaning of what should be contained inside of them. The div and span elements, for example, says nothing of what it contains. However, the p element is used specifically for paragraph text. Some of the common semantic elements of HTML5 are listed below.

<header>
Defines a document header, usually containing logotype and/or navigational links.
<main>
Should contain the main content of the HTML document. Only one main element is allowed per HTML document.
<footer>
Defines a document footer, usually containing contact details or copyright info.
<nav>
Outlines a major block of navigation links.
<article>
Should contain content that stands on its own, such as a blog post or a news article.
<section>
Defines a section of the web document. Can be used to define sections of an article or sections of the document itself.
<figure>
Defines a figure and usually contains an img element together with a figcaption element.

The purpose of these tags is to help visually impaired users that uses screen readers to omit content that is repeated across a website (such as headers, navigation and footers) in order to get to the vital and unique information of a web document (the main content or an article). They are also very good for developers in order to understand what content should be placed where when working with HTML and an important part of HTML code hygiene.

Let's use some of the new HTML5 semantic tags. First, add a <main> tag around the content you just created (and don't forget to close it at the right position!). Here is a simple example how <main> works:
Burger Pub
                                    
                                    <body>
                                        <main>
                                            <h1>Välkommen till Burger Pub</h1>
                                        </main>
                                    </body>
                                    
                                
Then, since we have two different part of our websites, one for selecting burgers and one for entering customer information, let's add <section> tags around each of them.

Finally, add a footer to the website before the </body> end tag.
In footers you will often see the copyright information of the website, most often with a copyright sign in front. There are instances when you wish to place special characters in an HTML document and this is done with the following syntax: &code;. The code can either be a predefined entity or a number. In this case, the entity for a copyright sign is "copy". If you ever need to add less than or greater than signs in your HTML document that should be displayed, you cannot do it by using the angle brackets since these are a part of the HTML nomenclature. Instead you should use &gt; for the greater than sign and &lt; for the less than sign. The W3C has a list of different special character entities and numbers that you can use in your HTML documents.

To separate your footer from the rest of the website, you can add a horizontal line: <hr>

Block and In-line

Elements allowed in the body are normally either rendered as block or in-line elements. Browsers usually interprets block elements such that it fills the space of its parent element's width and is also provided with a line-break before it is introduced (cf., hitting the enter key in a Word document). An in-line element, on the other hand, only uses as much space as its content needs. The <p> tag is an example of a block element whilst the <a> tag is an example of an in-line element.

In-line elements are placed inside some block element. However, it is a violation to place block elements within in-line elements. This means that <p><a>A link</a></p> is allowed but <a><p>A paragraph as link</p></a> is not. Semantically, it does not make sense to put a paragraph within an anchor (link), and the same goes for all block elements.

The code example below contains a heading, a division, and a paragraph with an in-line element along with some in-line elements on their own. The in-line elements are spanning, anchor, and image.

Block and in-line elements in HTML
                        
                            

This is a block element

This is a block element

This is a block element with an in-line element placed inside

This is an in-line element This is an in-line element Span

Running the above code in a browser would render the output presented in Figure .

Block and in-line elements
Example of how a browser renders block and in-line elements.
The code above gives you an example how you can influence the size of your image. By either setting the height or width of the image, you can tell HTML how large the image shall be displayed. You only need to set one of the properties and HTML automatically calculates the other one.
Now you have all the knowledge you need to add another heading to the first section, below the first heading and text that describes this section. The new heading should contain the name of your first burger. Now, search for an image of a burger on the internet and add the image below the headline (the code block just above this task includes an example of how to add images from the internet).

Your current website should look something like this:
Screenshot of an intermediate step of the first task

Lists

There are three types of lists that can be displayed in HTML5: (1) ordered, (2) unordered, and (3) description lists. The three types are displayed below. Both the ordered and the unordered list contains the <li> tag, which stands for list item. The description list takes two elements for each item to be listed: (1) a defined term (<dt>) and (2) a corresponding defined description (<dd>).

List elements available in HTML5
                        
                            
  1. Samuel Adams Boston Lager
  2. Marble Brewery Earl Grey IPA
  3. Innis & Gunn Oak Aged
  • IPA
  • Red Ale
  • Imperial Stout
Ale
A top fermented beverage
Lager
A bottom fermented beverage

The resulting lists as they would appear in a browser are depicted in Figure .

How lists are displayed in the browser
How lists are displayed in the browser.

So, if you want to make a list that is numbered, use the <ol> tag and populate it with <li> elements. Similarly, if you only want to list things in no particular order, use the <ul> tag. Finally, if you want to provide the user with some definitions, use the <dl> tag and use the <dt> tag to define your term and the <dd> tag to describe your term.

Now, add some information about your product in a list under the item. You should at least add some information for allergic people, for example if it contains gluten or lactose. You can just invent that information; there is no need for it to be accurate.

Tables

Tables in HTML are built up using table rows (<tr>) and table data (<td>). These are written within the <table> tag. The table is divided into three parts: (1) the table header (<thead>), (2) the table body (<tbody>), and (3) the table footer (<tfoot>). Only the body of the table is required, header and footer is optional. Cells in the header is defined using <th> to distinguish its content from table data.

An example of an HTML5 table
                        
                            
Beer name Type Price
Samuel Adams Boston Lager Lager 69.00
Marble Brewery Earl Grey IPA India Pale Ale 79.00
Innis & Gunn Oak Aged Ale 55.00
Total SEK 203

The resulting table as rendered by a browser is depicted in Figure . Notice that the last row of the table, the tfoot, only has two cells. Here we have used the attribute colspan which modifies the td element to span across several columns. There is also a rowspan attribute which will make a cell span across several rows in the table. Also note how the table header cells display the text in bold in order to differentiate the header from the data in the cells of the table body.

An example of a table displayed in the browser
In plain HTML, tables are your easiest option to structure your content in multiple columns. Search for at least two more burger images and display them on the website so that three products are displayed in one row. The headline, the image and the list of information should all be aligned properly for all three products.

Your website is now almost done and it should be similar to this: Screenshot of an intermediate step of the first task
One property that becomes handy when working with tables, among others, is align. It takes the values left, right, center and justify. It will align the element within the parent element or the document. It does not only work for tables but for most other elements as well.

Forms

Something you see often in websites are forms that users can fill out, either to update user information or to get in contact with the company handling the website.

Form
                            
                                

A <fieldset> element can be used to group different parts (fields) of your form.

Text Input

Input
                        
                            



The input element takes a multitude of attributes to specify its use. The placeholder attribute adds a label inside the field that disappears when the user enters text into the field. Whilst the required attributes defines the field as mandatory and the form cannot be submitted without it being filled in. However, these attributes are new features as of HTML 5 and therefore older browsers might not support these input attributes.

Elements can be given names, and in the case of forms, the name attribute is used when the data of the form is sent in order to keep track of the information in the form elements. Thus, this is a required attribute for form elements that contain user defined data.

The email value of the type attribute defines a special type of text field that, in contrast to a normal text field, has restrictions on its input. Modern browsers will make sure that the input in the field is formatted as an e-mail address. This you would otherwise have to handle via JavaScript. There are other special types, such as number and url. Over at W3C you can read more about HTML input types.

Input Labels

Before the first two <input> tags in the example above, you can see that we added label elements. These elements are paired with a corresponding input element to give it a label. This pairing means that if the label is clicked, the paired element is selected. To pair the label with an element, simply add the for attribute and give the id of the element you wish to pair as a value of this attribute.

Add four text input fields to the second section of your page:
  • First- and Last Name (in one field)
  • E-Mail Address
  • Street
  • House Number (only allowing numbers in this field)
Add labels and placeholders to the fields so the second section looks something like this: Screenshot of an intermediate step of the first task

Drop Down List

Drop down lists in forms are used to give users the possibility to choose a single option. Within a select element you place <option> tags that hold the different options available to select from the drop down menu.

Now we want to offer different payment methods to the customer. Below is an example how drop down lists are created. Change this example so you can select one of at least four different payment methods. The most popular one should be pre-selected.
Drop Down
                        
                            


If you would like to allow for users to select more than one option you would add the multiple="multiple" attribute to the select element. The select element will then be displayed as a list rather than a drop down menu.
If you wish to provide the users with pre-selected values, simply add the selected="selected" attribute to the option element you wish to be pre-selected.

Long Text Input

When a user needs to provide larger amounts of texts as input, you use the textarea element.

The size of the textarea element can be adjusted by defining the cols and rows attributes, where the former adjusts the width and the latter adjusts the height of the element.

The amount of text a user is allowed to provide can be limited with the maxlength attribute. As a value you enter a number representing the maximum number of characters allowed to be entered into the text field or area.

Radio Buttons

Radio buttons are a way to provide an input element where only one option is valid. You can off course use a drop down menu for this. However, they should be reserved for longer lists only where you need to save visual space in order to keep your form uncluttered. Radio buttons is ideal when you only have two or three options to choose from since they are quicker to interact with since an option only needs one click to be selected.

Radio buttons are created similar to text input fields, but the type is "radio" instead of "text".

With this input element, the label becomes a necessary component since the element only displays the actual button. You can just use any element that displays text, however, for usability a label is a better choice since clicking the label will select the option.

The checked="checked" attribute allows you to provide the user with a pre-selected option.

Please notice that the name attribute must be the same for each radio button, this in order to tell the browser that these should be grouped together. Don't forget to set the "value" option in order to be able to know which radio button was selected later on.

Ask for the gender of the customer (male, female, do not wish to provide) using radio-buttons. One of the items should be pre-selected. If you are not sure how the code for radio buttons look like, use Google to find the answer. By now your understanding of HTML should be good enough to understand and use the code snippets you will find. W3schools is always a good starting point if you search for HTML code!

Check Boxes

If you wish to allow for users to select more than one option, you can simply change the value of the type attribute from "radio" to "checkbox".

Submit Button

A submit button is a special type of button that is used only for submitting form data. You can place other buttons both inside and outside of the form element. However, a submit button placed within the <form> tag will be tied to the form and once the button is pressed by the user, the form is submitted.

Submit Button
                        
                            
                        
                    
All input elements that show text can take the attribute value. Whatever you put as a value to this attribute will be displayed by the input element. Thus, it can be used to provide a pre-defined value in text inputs for example. In the case of buttons, the value will be presented on the button.

If you wish to display images in your buttons, you can use the button element instead. Within it, you can place HTML tags.

Button With Image
                        
                            
                        
                    

The above code will render a button with an image. Figure depicts how it might be rendered in a browser.

A button with an image
A button with an image.
Your last task for the HTML tutorial is to place a button at the bottom of your page, after the second section but above the footer. The button should submit the order, so name the button appropriately and find a good image that represents this. As mentioned earlier, submit buttons perform a specific function if located inside a form, but this is not what we want here (in a later part of the tutorial) so it is intentional that we place the button outside of the form.

The final website you should have after completing all these steps should look like this: Screenshot of first task Keep your code for the next part of the tutorial. When introducing CSS, we will add a styling on top of this simple website to make it a little more beautiful.

CSS

Your Task

Get ready to add some style to your HTML.

In this part of the tutorial you will learn the basics of CSS. To do this, we will continue to build upon your code from the HTML part of the tutorial.

After working through the CSS part, your website should look something like this:
Screenshot of second task

Formatting of Web Pages

The acronym CSS stands for Cascading Style Sheets and is a formatting language used on the web together with HTML. HTML is only intended to structure information, but in the early 90's different browser developing companies started introducing HTML tags that also formatted the content. Tags such as <font>, and <color> started popping up. In order to avoid developing HTML in this direction, to maintain a separation between form and content, CSS was introduced. Where HTML defines the structure of content, CSS adds formatting and style. This separation provides a streamlined way of handling formatting of HTML documents. The idea behind how CSS works is based on the observation that you often want the same formatting to apply to tags of the same type, or that you use for a similar purpose. To take advantage of this, coding in CSS means that you declare how you want to format a certain tag and then the formatting cascades throughout all tags of this kind in your HTML document(-s). This is much more convenient than individually defining the formatting every time you use a tag. With the multitude of tags available to us, and all the parameters that we can use for formatting, this means that we get less clutter in our code and avoid a lot of menial work on updating each use of a tag every time you want to change the formatting of it.

Rules

A CSS document is a text document that declares formatting rules for HTML elements. In the code example below we see, for example, how any text encapsulated by the <body> tag will be formatted with a Droid Serif font in a size of 12 points.

Basic structure of a CSS 3 document
                        
                            @import url("reset.css");
                            @import url("https://fonts.googleapis.com/css?family=Droid+Serif|Share+Tech+Mono");

                            body {
                                font-family: "Droid Serif", sans-serif;
                                font-size: 12pt;
                            }

                            a, strong, em {
                                color: #0099ff;
                            }

                            p.info,
                            #login p {
                                width: 80%;
                                margin: 1vw auto;
                            }
                        
                    

A CSS rule is initiated by a selector which signifies what element or elements that should be formatted (Figure ). Multiple selectors are separated by a comma. The selector is either the name of the element class (such as body, p, table etc.) to signify that the rule regards all instances of the particular element, or a unique id which identifies a specific instance of an element, or it can also be a class which instances of elements belong to (read more about id and class under the Attributes section in the HTML tutorial above, and read more about selectors below).

Each CSS rule is declared with a formatting property and a corresponding value. All declarations are listed within curly brackets (i.e., { ... }) and the property and value are separated by a colon, whilst the declarations themselves are separated by a semi-colon. As long as these rules are followed, any whitespace character (tab, line break, or space) can be used to make the code more readable without interfering with code execution.

The anatomy of a CSS rule
The anatomy of a CSS rule.
There are also special types of rules called at-rules. These rules begin with an @ sign and an example is shown above in the CSS structure example: @import. This at-rule imports a CSS document and makes use of its rules. There are also so called nested at-rules which hold CSS format rules embedded in curly brackets and used either to separate designs for different devices (@media), define and make use of custom fonts (@font-face), or define styles that only applies when printing a page (@page) among others.

Where to Put Your CSS

There are three ways to include CSS code in your HTML document: (1) as an external style sheet document, (2) as part of the <style> tag within the <head> tag of the HTML document, and (3) declared in-line within an HTML element in the style="" attribute. Generally, CSS should be declared through the first alternative in order to keep content and form separated. There are instances where you need to add style directly inside your HTML document, but this should be kept at a minimum in order to keep your website easy to handle when it comes to making changes. You do not want to go through a lot of HTML documents in order to restyle some HTML elements. Thus, the first of these three alternatives should generally be employed.

Please keep in mind that your Node server is configured to use the public folder as its root folder. This means that you should enter all paths to local files as if your index.html was located in the public folder. Doing so means that your images, CSS, and JavaScript files that you've linked to on your index.html page will only load correctly when you access it through the http://localhost:3000 address. If you instead open the index.html file directly by e.g. double-clicking on it, your browser will use the views folder where index.html is located as the root and won't find what it is looking for.

To create an external style sheet, simply create an empty text document and fill it with your CSS rules, then save the document with the .css file extension. The style sheet is then linked to in the HTML document inside the <head> by adding the tag <link rel="stylesheet" type="text/css" href="path/to/style-document.css">. If the document is local, then the path to the document has to be relative to where the HTML document is placed. If you use a server, like node.js, the css and javascript files have to be located in a special folder so the server can find them. Take a look at the provided code and locate the sample css file if you don't know where to store your css file. Alternatively, it can be a style sheet online with an absolute path (e.g., http://www.mysite.com/css/style.css).

CSS files can be used by a single HTML file or they can be included in multiple or even all HTML files within your project. Projects therefore often have global and local CSS files. It is okay to start writing CSS rules only for a single HTML file. But before you start to copy and paste CSS code from one style file into the next one, it is time to create a more global style file with common rules for a multitude of HTML files.
Create an empty text document in the correct folder within the given project code and name it style.css. Within the <head> tag of your HTML file, add the code to reference this newly created CSS file.

Comments in CSS

To add comments to your CSS code (which you should), you can use /* Your comment goes here */. This is also very helpful when you wish to comment out code when you are debugging or trying out new designs.

Fonts and Text Styling

When using fonts in CSS, the font is usually provided by the client (i.e., the user's computer). However, it is possible to use your own fonts by uploading them to a server and link to them in your CSS. There are also font libraries online which let you use their fonts. For example, Google has a large library of fonts.

External Font
                        
                            @import 'https://fonts.googleapis.com/css?family=Pacifico|Dosis';
                        
                    

To define fonts, we use the font-family property. There are two kinds of families when it comes to fonts: (1) generic family, and (2) font family. All fonts usually belong to one broader generic family: (1) serif, (2) sans-serif, or (3) monospace, for example. Serif fonts have small lines at the end of most of their characters. The most common serif font is Times New Roman. Sans-serif simply means without serif and most common sans-serif font is Arial. Finally, monospaced fonts are fonts where each character has the same width and they tend to look like old style typewriters. The most common monospace font is Courier New. Generally, sans-serif fonts are regarded as being easiest to read on screen whilst serif fonts are regarded as the easiest to read for print.

A font family is simply a specific font (e.g., Times New Roman, Arial, or Courier New). You can define several fonts separated by commas for an element in case your top choice is not available. The convention is to provide at least one font-family and then end with a generic family to make sure you get as close to the intended web design if the specified font is not available (e.g., font-family: Arial, sans-serif;). The browser will then make use of a font from the generic family when the specified font cannot be loaded. Font names that contain more than one word always need to be wrapped in quotation marks (i.e., "Times New Roman" or "Courier New").

Be aware that not all browsers display custom fonts as a security measure. This means that you should as much as possible make use of common fonts that will be present on most users' systems. Or, at least make sure that your web design is not dependent completely on a specific font.

Common Font and Text Properties

color
Sets the colour of the text. Use any of the colour methods provided in the Colours section.
font-size
Sets the size of the text. Use any unit defined in the Units section.
font-style
Used to specify italic text. As a value, the property can take italic or normal
font-weight
Used to specify bold text. As a value, the property can take bold or normal
text-decoration
Adds a line under, over, or through the text. Values allowed: none, underline, line-through, or overline
text-transform
Changes the casing of text. Values you may use: none, uppercase, lowercase, or capitalize
line-height
Defines the spacing between text lines.
text-align
Aligns text in an element with values: left, center, right, or justify.
In the style.css file, add your first css rule by changing the font of the whole body. Below is some example code, but play around with it a little and select a font you like for your website.
Body Font
                        
                            body {
                                font-family: arial;
                            }
                        
                    
Now we have declared a base line font for the web site that all children of the body element will adhere to. Save the file and reload localhost:3000/ in your web browser to inspect the layout changes of the page.

Units

In CSS there are several ways of expressing lengths. They are categorized into either relative or absolute units. Units are expressed using a number and the unit without any whitespace (i.e., 5px). The most common units are presented in the two tables below.

Relative Unit Explanation
em Relative to the element's current font size, 2em would be twice the size of the current font
vh Relative to the height of the view port, 2vh is 2% of the height of the browser's view port
vw Same as vh, only that it relates to the width of the view port
% Relative to the parent element size, 50% would be half the size of the element's parent

Relative units are very handy to use when you wish to create a resizable design in order to cater for responsiveness in relation. This is important since users visit your web page from very differently sized devices.

Absolute Unit Explanation
cm Centimetres
in Inches
mm Millimetres
pc Picas, 1 pica equals 12 points
pt Points, a point is 1/72 of an inch and is a common unit for font sizes
px Pixels, these are relative to viewing devices resolution
The original font size is a little small to be well readable. Change the base font size of the whole body so it is a little larger than before.

Colours

There are three ways to declare a colour in CSS supported by all major browsers: (1) hex triplets, (2) RGB, and (3) predefined colour names. There are 140 predefined colour names and the way they are declared is simply by typing their names (black, blue, orange etc.) as the value of a colour property.

Both hex triplets and RGB colour values are set by declaring the level of red, green, and blue to be part of your final colour. To define the colour red in RGB you would write rgb(255, 0, 0). Here you set the intensity of each constituent colour by providing a number between 0 and 255. To define the colour red in hex triplets you would write #ff0000. Here the intensity of each constituent colour is instead defined between 00 and ff (which in hexadecimal notation represents 0 to 255) where the first two integers define red, the second two green, and the last two blue. The benefit of using RGB or hex triplets is that you can be more precise with your colours since it allows for a lot more colour combinations than the 140 predefined colour names (16 777 216 to be precise). Hex triplets is the most common way to define colours, simply because it has a shorter notation.

Selectors

Selectors are divided into four groups: (1) basic selectors, (2) combinators, (3) pseudo-elements, and (4) pseudo-classes. We will go through these groups of selectors in order to see how they work.

Basic

There are five basic selectors: (1) type, (2), class, (3) id, (4) universal, and (5) attribute. The first three are the ones you will use the most, but let's go through them all one at a time.

Type
A type selector is defined by simply writing the name of the element (such as p or section) which is the selector which you have currently used in the webpage CSS file (i.e., html and body).
Class
A class selector is defined by writing a full-stop followed by the class name that you have defined in your HTML document.
Below is an example of how you select a certain class. In our HTML document, we currently have no specific classes, but let's change this! Now, since we consider it important for the user to easily see which ingredients are in a certain product: Go back to you HTML document and add some grouping tags arounds the ingredients like "gluten, lactose" without changing the structure (take a look back at the Common HTML Elements if you are not sure which one to choose). Give those tags a class definition, the same for all of them. Now go back to your CSS file and set the text to be bold for this specific class.
Class in HTML
                                        
                                            <section class="classname">
                                                <p>A block element <span id="idname">with an in-line element </span></p>
                                            </section>
                                        
                                    
Class Selector in CSS
                                        
                                            .classname {
                                                color: #ff5500;
                                            }

                                            #idname {
                                                text-transform: uppercase;
                                            }
                                        
                                    
You can also be more specific with which element belonging to a specific class should be targeted. If you would write a.current, only anchors belonging to the current class would be affected but not any other elements that belongs to the same class.
ID
When using an ID selector, we are targeting a unique element node in the DOM structure. The ID must always be unique and there can thus only be one element with the specific ID within a single HTML document. However, you are off course allowed to use the same ID in several elements as long as they are in separate HTML documents. An ID selector works similar to a class selector, but a # is used instead of a full stop.
You already learned how to define different colors. Go back to your HTML code and give the two sections you have for your burgers and your order information two different IDs. In you CSS, give one of the sections a black background and a white text color. For now, don't add any formatting to the other section.
Universal
The universal selector (*) selects all elements in the HTML document if used on its own, or it selects all elements within an element if used in combination with a type selector (e.g., div *). It can also be used to select all elements within an element containing a specific element. For example, if you write section * p as a selector in your CSS document, you will target the all elements that are placed within a section element provided that they contain a p element. This selector should be used sparingly since it can significantly reduce the speed of loading a large HTML document in a resource limited device.
Attribute
The attribute selector will target any elements that have the attribute specified or which have the value of the specified attribute. The attributes (and their values) are specified within square brackets (i.e., [...]).
Attribute Selector
                                
                                    input[type="radio"] {
                                        height: .7em;
                                        width: .7em;
                                    }
                                
                            
You can also use this selector as a more general selector. Below is a table with different ways you can make use of the attribute selector.
Selector Explanation
[class] Selects all elements that has the class attribute, regardless of its value.
div[id] Selects all div elements that have the id attribute, regardless of its value.
input[type*="button"] Selects any input elements that have a type attribute whose value contains the string "button".
input[type^="but"] Selects any input elements that have a type attribute whose value starts with the string "but".
input[type$="on"] Selects any input elements that have a type attribute whose value ends with the string "on".
You can find a list of all the operators over at the Mozilla Developer Network.

Combinators

HTML elements are always nested within another which creates a parent/sibling relationship between the outer and inner element. This relationship can be exploited when you wish to do very specific formatting of your website. To make use of the relationship, so called combinators are used and there are four kinds of combinators in CSS: (1) descendant, (2) direct children, (3) adjacent sibling, and (4) general sibling.

Descendant (space)
To format any children, or grandchildren, of an element, the descendant combinator can be used. It simply means using a white space between selectors. So for example, section p would mean that any paragraph elements placed inside a section element will be formatted with the given conditions within the rule.
Direct Children (>)
To select any children directly situated inside an element, the direct children combinator can be used. For example section > p would select any p elements directly placed within section elements, but not if they are grandchildren of the section elements.
Adjacent Sibling (+)
The adjacent sibling combinator selects a sibling that directly follow the target element. Using table + p as a selector means that any paragraph that follows directly after a table will be the target of this rule.
General Sibling (~)
In contrast to the adjacent sibling combinator, the general sibling combinator selects all siblings placed after a given element, regardless of whether they are adjacent or not. Using div ~ p as a selector would select all paragraphs that are siblings with a divider, provided they come after the divider, and regardless of whether there is another element between them.

Pseudo-Elements

Pseudo-elements are used in selectors to style only parts of elements. In CSS3 these are generally used for manipulating appearance of text and they are currently five.

Pseudo-Element Selector Description
::after Insert something after the content of target element
::before Insert something before the content of target element
::first-letter Selects the first letter of target element
::first-line Selects the first line of target element
::selection Selects user selected text

Pseudo-Classes

A pseudo-class is a keyword added at the end of a selector using a colon and specifies a particular state of the targeted element. It lets you apply styles that are not directly related to the structure of the HTML document but also the status of its content. There are currently 40 pseudo-classes that you can use. For a full reference, check out the pseudo-class list over at the Mozilla Developer Network.

We can change the hover colour of a button, for example, by using the pseudo-element selector below. Add it to your style.css file and change the background color. Something else you often see on websites is that the cursor changes if something is clickable. Use Google to see how to change the cursor and then add this to the button hover as well.
Pseudo-Class Selector
                        
                            button:hover {
                                ...
                            }
                        
                    

If you wish to apply a CSS rule to more than one element, you simply separate your selectors with a comma (e.g., div, p::first-letter, a:hover{ ... } ).

CSS Specificity

In order to decide which style is applied to which element, browsers make use of what is called specificity. For example, any style formats given an element through inheritance from a parent can always be overridden by specifying the child element as a selector. For example, any styles given to a p element by its parent div can be overridden by defining rules with a p selector. Furthermore, if styles are applied to, for example, a p selector, they can be overridden by being more specific and using div p as a selector. Type selectors and pseudo-elements have the lowest priority, next after that comes class selectors, attribute selectors, and pseudo-classes. Finally, ID selectors are given the highest priority in a CSS document. This means that giving a unique ID to an element and targeting that ID within your CSS document is the safest way to override any styles provided by other selectors. The universal selector and combinators do not have any effect on specificity. Any inline styles declared within an HTML element (e.g., style="font-style: italic;") will always override styles declared in a CSS document.

Box Model

All HTML elements are essentially rendered as rectangles in browsers. There are basically five properties that determine the final size of an element: (1) content width, (2) content height, (3) padding, (4) border, and (5) margin. Figure illustrates these properties. This is called the CSS Box Model.

The CSS box model

The content of an element will usually be text or an image and the size can be manipulated by modifying the width and height properties. Any element can have a border set around it with a user defined colour. The width of the border adds to the total width of the element. To create some space within the element, between its content and its border, you can manipulate the padding property. Padding can be considered an expansion of the content since any background colour declared for the element will also be rendered in the padding part of the element. In order to specify some space between elements, you manipulate the margin property which is an area surrounding the border of the element.

Width and Height

To set the width or height of an element, simply declare height: 20px; for example, to make the content part of the element 20 pixels high (see the Units section for more size units). Notice that there is no space between the number and the unit.

You can also declare a minimum or a maximum width or height. This means that, regardless of the size of the user’s device, an element will never be smaller or larger than the given value. If the screen of the user device is too small to fit the given element, a scrollbar will be added to accommodate for the size.

The table is currently quite compressed. We can give all the items a little more space by defining a width for our <table> element within CSS. Try to use percent as a unit of measure and experiment with different sizes of the table. Depending on your size of the table, it might look better if it is not aligned to the left but to the center of the page. Try this as well to find a good styling for your table.

Padding and Margin

The padding and margin sizes are declared similarly to the height and width, although, padding and margin can also be individually adjusted for both top, bottom, right, and left. Declaring, for instance, margin: 20px; will increase the margin equally for all four sides. To only adjust one of the sides, simply add the name of the direction in which you would like to adjust the margin or padding (i.e., padding-right: 5px; or margin-top: 50px;).

If you wish to individually adjust margin or padding in the four different directions, you can also use different short-hand versions.

Short-Hand Example Affects Explanation
margin: 1px 2px 3px 4px; margin: top right bottom left; Top margin is 1px
Right margin is 2px
Bottom margin is 3px
Left margin is 4px
padding: 1px 23px 4px; padding: top right/left bottom; Top padding is 1px
Right and left paddings are 23px
Bottom padding is 4px
margin: 5px 10px; margin: top/bottom right/left; Top and bottom margins are 5px
Right and left margins are 10px
padding: 5px; padding: top/bottom/right/left; Top, bottom, right, and left paddings are 5px
margin: 0 auto; margin: top/bottom right/left; Top and bottom margins are 0
Right and left margins are automatically set to fill the rest of the screen which centers the element. In order for this to work, the element must have an explicated width.
The section headings and texts look a little bit close to your browser window border, so let's add a margin to change that. You can either add the margin for both sections separately or for the type <section> in general. If you are already at it with adding margins, how about giving the button a little more space so it is not sticking so close to the last section?

Border

In contrast to margin and padding, where only the size can be manipulated, borders can also be manipulated visually in both colour and style. Similar to margin and padding, borders can be manipulated in the four directions: top, right, bottom, and left. You either declare all three values at once using the border property (e.g., border: 1px solid #ff0000;) or individually by using the border-width, border-color, or border-style properties respectively. The different border style that can be used are illustrated in Figure .

None
Solid
Dashed
Dotted
Double
Groove
Ridge
Inset
Outset
All border styles

In order to manipulate the border in different directions, simply add the direction to the border property you wish to manipulate. So if you wish to manipulate the right side border style use the border-right-style property. Or if you wish to manipulate all three values, use the border-right shorthand.

Property Affects Illustration
border: 2px solid #ff9900; Solid border around the entire element
border‑left: 2px dotted #ff9900; Dotted border only on the left side of the element
border: 2px solid #ff9900;
border‑bottom: none;
Solid border around the element with the bottom border removed
border: 2px solid #ff9900;
border‑top‑color: #000000;
Solid border around the element with a different colour on the top border
Let's separate the sections even more by adding a border around them. How about a dashed line in the respective color of the section's text? When adding the border, you might realize that it is very close to the text inside the section now, at least at the left border. Make the respective changes and give the text some more space towards the border.
The border-radius property is used to curve the corners of borders and backgrounds of elements.

Display

With the box model comes a few pre-defined boxes that can be used as properties in CSS. In the HTML tutorial we talked about two in particular: block and in-Line. With the display property, we can change the pre-defined box of elements and turning block elements into in-line elements and vice versa. Or we can make it a combination of the two, that is, an inline-block. You can also set this property to none in order to hide a selected element. Visit the MDN page for a more complete reference of different box models.

Handling Cross-Browser Compatibility

All HTML elements are rendered pre-defined sizes depending on the type of element. For example, all block elements are rendered with 100 % width, but the height is dependent on the content of the element. With an in-line element, on the other hand, both height and width is dependent on its content. And for heading elements, a type of block element, margins are pre-defined as well as font-sizes for the text content. A general problem is that these predefined values vary from browser to browser, creating problems to get your web site to look the same in all browsers.

One way to handle some of cross-browser compatibility issues is to use a so called CSS reset file. This file removes a lot of pre-defined CSS rules which allows you more control over your website style. You can download a reset.css file from meyerweb.com and place the file inside your webpage/css folder. Make sure to include this CSS file into all of your HTML files as outlined in the Where to Put Your CSS section. Please make sure that you place the reference to this CSS file before the reference to the style.css file. The reason being that we do not want the rules of the new CSS file to interfere with already defined rules (see the CSS Specificity section for more information).

You can download the file and try using it. If you do, you should now notice that all margins have been set to 0 and all fonts have the same size. The reason is to make sure that we specify these values explicitly since different browsers give different values for these properties. For now, you can either remove the file again or specifiy all font-sizes by hand before continuing so you have the same layout as before.

Background

There are five background properties that can be adjusted on an element:

background-color
Sets the colour for the background of the selected element. Use any colour method discussed in the Colours section.
background-image
Loads an image as background of the selected element. As a value, provide the link to the image in this format: url("path/to/image.png");. Supported image file formats are generally: PNG, JPEG, and GIF.
background-repeat
Defines whether the background image should be repeated. Allowed values are: repeat-x for horizontal, repeat-y for vertical, repeat for both horizontal and vertical repeat (this is the default), and no-repeat for disabling the repeat.
background-attachment
Defines what happens with the background image when page is scrolled. The value can be set to: fixed so that it does not scroll, local so that is scrolls with the element's content, or scroll so that it scrolls along with the element (this is the default).
background-position
This property sets the starting position of the image. This property takes two values; the first one is for horizontal position and the second one for vertical position. The value can either be left, center, or right for the former and top, center, or bottom for the latter. Alternatively, you can provide a number and a unit for each of the two values to specify exactly where the image should be positioned.

There is also a shorthand for giving all background properties in one declaration: background: #colour url("path/to/image.png") no-repeat scroll left top;. The order in which the properties are given is the same as they have been presented above.

This task is the most tricky one. If you look back at the image of our final website that we want to create, you will notice that only the background image behind the first headline is missing. So let's add it!

First, we need to load the image inside the HTML. So go back to you HTML file, select a header image from the internet and load it right after the definition of the headline. You don't need any property in HTML, so no need for defining a size or anything, we will do this in the CSS. If you haven't done it before, group the headline and the image together using an appropriate tag. If you are not sure which one to use, take a look back at the Document Structure Elements again. If you load your page now, the upper part will look something like this: Intermediate step when adding the header image

Back to your CSS. The first thing we want to make sure is that our whole header (meaning the image and headline, so use the ID or class given to that structure element) has the same margin to the left and right as our boxes below. So add this value to your group. If you reload, you notice that both the image and the headline moved to the right and are now in line with the border of the sections.

The next step is to make the image more transparent so we will be able to read the text on it. You can address the image either by giving it an ID or by using the ancestor addressing model introduced above. The property you need is called opacity and it takes values between 0 (fully transparent) and 1 (solid). Add this property and an appropriate value to the image and re-load the page.

Before we can place the text on the image, we need to learn about one more property.

Layout

Elements on a web site are normally placed in the general flow of the HTML document, meaning that block elements are placed beneath earlier ones whilst in-line elements are placed directly after one another. There are CSS properties that can disrupt the standard flow in order to redesign the layout of a website. These properties are display (which we have covered), position, and float.

Position

The position property can be used to change positioning method of an HTML element. There are four methods that can be specified as a position value: (1) static, (2) relative, (3) absolute, and (4) fixed. A directional property is then used to manipulate the position of the element (i.e., top, bottom, right, and left) which are given a number and a unit which entails how much the element should be offset in the given direction.

Value Explanation
static This is the default value and simply means that the element follows the standard flow of order.
relative The element is offset from its normal position by the value of the directional properties.
absolute The element's standard position is ignored and instead it is offset from the position of its closest non-static ancestor by the values declared in the directional properties.
fixed The element's standard position is ignored and instead it is offset from the browser's view port by the values declared in the directional properties.

Float

The float property moves an element from the normal flow and places it to the right or left in its parent. The possible values for this property are: left, right, and none.

Now it's time to add the text on top of the image. Simply add the attribute of an absolute position to the headline (address it similar to the image in the step before). You will notice that it is now on top of the image, but in the very top left corner. No problem, we can fix this later when we have the final size of the image, because currently it is a little large.

Give the whole group of headline and image a height attribute (select an appropriate height yourself). If you re-load the page, you notice that there is now probably some overlap between the image and the section. Fix that by adding overflow:hidden to the group.

Almost there! Now your image might be a little bit too short. Set the width attribute of the image in CSS to 100% and the height to auto. Now, play around with the padding of the headline and select one that looks good to you and the header is done.
You might realize that not just your header image but your headline on top appears slightly transparent as well. This is because it is actually positioned under your image. If you want to have the headline solid again, switch the order of the image and the headline. You will see the headline somewhere inside your burger ordering section. Use margin-top with a negative value to bring it back to the intended position.

Grid Layout

If you use only HTML, tables are the easiest option when it comes to layouting your content using a row- and column-based styling. However, you will quickly realize that tables are quite inflexible and creating stylings where content reaches over multiple rows and/or columns is difficult to achieve. With CSS, we have a more powerful styling tool to use now: grid layouts. Grid layouts use the same idea of rows and columns, but they are much easier to create and alter than pure tables. Let's assume we want to create the following content: Grid Layout

In HTML, you only need to create an outer div which the grid layout is applied to. This is similar to the definition of a table as the container for the individual rows and columns. Within this outer div, you then create the single divs, one for each block of content you want to style. Each div needs to be uniquely identified, usually by giving it a different class. Here is the HTML code for creating the example above:

Grid Layout (HTML)
                        
                           
A
B
C
D

And here is the CSS code:

Grid Layout (CSS)
                        
                           .wrapper {
                                display: grid;
                                grid-gap: 10px;
                                grid-template-columns: 100px 100px 100px;
                                background-color: #fff;
                                color: #444;
                            }

                            .box {
                                background-color: #444;
                                color: #fff;
                                border-radius: 5px;
                                padding: 20px;
                                font-size: 150%;

                            }

                            .a {
                                grid-column: 1 / span 2;
                            }
                            .b {
                                grid-column: 3 ;
                                grid-row: 1 / span 2;
                            }
                            .c {
                                grid-column: 1 ;
                                grid-row: 2 ;
                            }
                            .d {
                                grid-column: 2 ;
                                grid-row: 2 ;
                            }
                        
                    

The CSS part of the code should be easy to follow. First, we add the styling to the outer div by declaring the display:grid. The grid-gap defines that there is a gap of 10 pixel between the rows and columns. We can also set the gaps between rows and columns separately by adding grid-row-gap and grid-column-gap. grid-tamplate-columns defines the size of the three columns in our example. Here, each column has the same width, but they can be different from column to column as well. The color styling should look familiar from earlier in this tutorial already. The same holds for the styling of the class box. It only uses styling elements we have talked about in this tutorial already. Note that this is all optional styling for creating the sample layout in the image - neither the colors nor the paddings or borders are necessary for a grid layout.

Every box-div has an individual class attached to it as well. This is where the styling-magic happens now! For each class, we can define in which rows and columns this div should be displayed. Box a, for example, starts in column 1 and spans 2 columns, which includes the one where it starts. So it will be displayed in the first and second column from the left. Box a has no explicit row definition. By default, this is interpreted as row 1. You could also explicitely add this and you would get the same result. Box b is only displayed in a single column, the right most one, but it spans two rows. Box c and d are small boxes which only use a single row and colum, but one is displayed in column 1 and one in column 2. In this example, there is no overlap between divs - however, this is very much possible in a grid layout as well.

Change your code to display the individual burger items so it uses a grid layout instead of tables. Visually, you should not see any difference between the table and the grid layout. However, your code should look much simpler and cleaner after you've changed it to the grid layout.

Responsive Web

What happens if you change the size of your browser window? Does it still look exactly like you would want it to look? Spoiler: It doesn't! Why not?

Users will visit websites on different devices with varied screen resolutions. To handle this, we can use so called media queries to provide different CSS rules for different screen sizes. An example of how to provide a media query is provided below.

Media Query
                        
                            @media screen and (max-width: 800px) {
                                h1 {
                                    font-size: 6vw;
                                }
                            }
                        
                    

This is an at-rule which hosts CSS rules nested within it. These rules only come into play when the conditions in brackets are met. In the example above, any rules pertaining to the h1 selector inside the at-rule will trigger when the width of the user's screen is less than 800px. For a list of different properties that can be used in these queries, please read more about media queries over at MDN.

The power of EM

Throughout this tutorial, we have used the em unit to define most of our lengths for paddings, margins, font-sizes and so forth. The reason for this is because this unit is relative to the font size of the nearest ancestor that has it defined (if none, then it will be relative to the browser pre-defined font size). In our case we set the font size to 30 pixels in the html selector. If we would declare a percentage unit to the font-size property of the body selector now, it will cascade throughout the entire website, making it easy to adjust all elements in response to screen sizes.

After your last task in your CSS tutorial, your website should look something like this: Final page styling Again, keep the code. The next tutorial will be about JavaScript and it will teach you how to add some functionality to your website, like the ability to actually click on the button.

JavaScript and Vue

Introduction to JavaScript

The most common confusion about JavaScript is that it is related to Java, this is not the case. It has jokingly been said that Java is to JavaScript as Car is to Carpet. JavaScript was developed at Netscape in the early 90's and was briefly called Mocha, then LiveScript. Netscape and Sun (the company behind Java) started cooperating and the idea was originally to make JavaScript a complementary language to Java. This did not happen, though, but over the years JavaScript has grown into a web standard scripting language implemented in all major browsers and its standardization is maintained by ECMA International. JavaScript is an interpreted, dynamic, weakly typed, prototype-based language and accesses objects in an HTML document via the Document Object Model (DOM), which is an application programming interface (API). By accessing HTML elements through the DOM, this scripting language can manipulate the look and behavior of web pages.

Before you continue with this tutorial, you will need a general introduction to JavaScript. For this, we recommend reading and working through the following chapters from the book Eloquent JavaScript (available for free as an online resource):
  • Introduction (from "What is JavaScript" onwards)
  • Chapter 1 (this should be a repetition from your previous programming class(es). Start off with the summary in the end of the chapter. If that all sounds very familiar to you, you can skip this chapter. Otherwise, read the chapter to refresh your memory on values, types and operators)
  • Chapter 2
  • Chapter 3
  • Chapter 4 (you may skip "The lycanthrope's log", "Computing correlation", "The final analysis" and "The arguments object")
  • Chapter 6 (only "History", "Methods", "Prototypes", "Constructors", "Overriding derived properties" and "Getters and setters")
  • Chapter 8 (only up to "Error Propagation")
If you want to get a deeper understanding of JavaScript, we encourage you to take a look at other parts of Eloquent JavaScript as well. However, for the purpose of this course, the content listed above will be sufficient.

Introduction to Vue

Vue (pronounced like "view") is a JavaScript framework that focuses solely on the view layer of your application and is considered suitable for designing interfaces. Vue is inspired by the MVVM pattern. MVVM is a software architecture pattern that separates the user interface from the back-end. The back-end code is grouped into the "Model", while the actual user interface is in the "View" layer. The "ViewModel" sits between the two and regulates their communication. These three groups form the acronym that gives the pattern its name: Model-View-ViewModel. Vue sees itself as the ViewModel layer of the MVVM-pattern. This is why the Vue object is often bound to a variable named "vm".

It is important that you understand that Vue is not a different programming language - it's a level of abstraction from JavaScript, that provides you with some handy functionality atop plain JavaScript to make your life easier. In the following tutorial, we will show you how to implement certain functionality both in plain JavaScrip and in Vue side by side, so you can see commonalities and differences between JavaScript and Vue.

Where to Put Your JavaScript

JavaScript can be accessed by the browser in pretty much the same ways as CSS is accessed, externally or locally: (1) as an external file, (2) placed within the <head> tag, (3) placed within the <body> tag, or placed as attribute values in elements in the form of special event attributes such as onload="" or onclick="" that are triggered at browser or user events.

It is highly recommended that JavaScript is kept in a separate file so that it can be more easily maintained and also this keeps function away from form and content which is neat and good programming etiquette. To add a JavaScript file to your document, simply use the <script> tag.

Locate the folder within the given project code that contains the JavaScript files and create two empty text documents, one called js_script.js and one called vue_script.js. Open your index.html file in a text editor. Link both the JavaScipt and the Vue file to this document by adding <script src="js/js_script.js"></script> and the respective line for the Vue script into the <head> of the document. Vue is nothing else than an external script (or library) that we have to include in our JavaScript file before we can use it. Therefore, we have to add <script src="https://vuejs.org/js/vue.js"></script> in the header of our HTML file above the import of the vue_script.js file.

Debugging and JSFiddle

As you have learnt from Eloquent JavaScript, using console.log() is very handy, especially when debugging JS code. When using Chrome or Firefox, you can load a JavaScript console, usually through the Tools menu or by right-click - "Inspect Element" and then switch to "Console" in the in-page window that opened at the left-hand side or bottom of your browser window.

To quickly test some JavaScript code, you can make use of JSFiddle.net. For debugging, you can use the browser console as described above. To test if it works, open a JSFiddle window and declare a simple variable, initialize it with 0 and print out the value on the console to make sure it works. You can also experiment with Vue in JSFiddle by just adding <script src="https://vuejs.org/js/vue.js"></script> to the top of the HTML part of your JSFiddle window.

Objects

You have already been introduced to the general idea of objects in JavaScript in Chapter 6 of the "Eloquent JavaScript" book. Here is a small example on how to declare and instantiate an object in JavaScript:

Object Constructor Function
                        
                            function Employee(fn, ln, branch, pos) {
                                this.firstName = fn; // The this keyword refers to the object itself
                                this.lastName = ln;
                                this.branch = branch;
                                this.position = pos;
                                this.name = function() {
                                    return this.firstName + ' ' + this.lastName;
                                };
                            }

                            // Objects are then instantiated using the new keyword
                            var emp = new Employee('Maike', 'Paetzel', 'Uppsala', 'PhD Student');

                            console.log( emp.name() ); // Output: Maike Paetzel
                        
                    

If you want to make use of Vue in JavaScript now, you always start with creating a new instance of the Vue object. You do that the same way as you instantiate other objects in JavaScript:

Creating new Vue Object
                        
                            var vm = new Vue({
                                //Here comes the optional elements of the Vue object
                            })
                        
                    
Instead of hard-coding the menu in HTML, you will in the following step by step learn to use JavaScript and Vue to display the burger menu on your website. First, create an object constructor function "MenuItem" and give it some properties, like the name of the product, the kCal and if gluten and lactose are contained. In addition, define a function that returns the name and the kCal of the product.
Try instantiating burger orders within JavaScript and print some of them out to your console.

Before we continue to learn what we can fill into this Vue object, we first need to understand how JavaScipt and Vue can be used in general to manipulate the HTML content.

The Document Object Model

MDN states about the DOM:

The Document Object Model (DOM) is a programming interface for HTML and XML documents. It represents the page so that programs can change the document structure, style and content. The DOM represents the document as nodes and objects. That way, programming languages can connect to the page.

Whenever you load a document in a web browser, the browser builds a model of the current document in the form of a tree structure. For example, the index.html document would be represented by the (partial) model depicted in Figure .

Representation of a DOM tree constructed when browser loads the HTML document

The Window and Document Objects

The window object in JavaScript represents the browser window. All global variables in JavaScript become properties of the window object and all functions become methods of the window object. With this object, we can communicate with the browser and, for example, manipulate the position of the scrollbar, display dialogue boxes, or the user's browser history of the current window. All window methods and properties can be found over at W3C.

The window object contains the document object, which is the representation of the HTML document in which the JavaScript code has been called. In the HTML DOM, everything is a node (the document itself, all elements, attributes, element content, and even comments). When the HTML document is loaded in the browser, it becomes a document object. This is the root node, that is, the ancestor of all other nodes.

Accessing Nodes

We can use methods of the document object to retrieve elements defined in the HTML document. The different methods either return one element object or a NodeList of element objects. A NodeList is an array-like collection of nodes that can be traversed or individual nodes can be accessed by their index.

Here is an example of how you can retrieve elements using plain JavaScript:

Get Nodes
                        
                            // To get an element with a specific ID, use getElementById()
                            var el = document.getElementById('anID');

                            // To get a NodeList of all elements of a specific class, use getElementsByClassName()
                            var els = document.getElementsByClassName('aClassName'); 

                            // To get a NodeList of all elements with a specific name, use getElementsByName()
                            var els = document.getElementsByName('aName'); 

                            // To get a NodeList of all elements of a certain type, use getElementsByTagName()
                            var els = document.getElementsByTagName('p'); // Returns all paragraph elements in the document
                        
                    

The above methods return node objects and these have properties and methods of their own. For example, you can read the el.previousSibling or the el.nextSibling property to get the node before or after a node. You can also get a NodeList of a node's children by using the el.childNodes property or a node's parent by using the el.parentNode property.

In Vue, there is no shorthand for getting elements by IDs or classes. However, we can just address elements in a similar way we address them in CSS within our Vue object:

Binding Vue Instance to HTML Element
                        
                            var vm = new Vue({
                              el: '#myID'
                              }
                            })
                        
                    

Within our Vue object, we now define that we want to address the HTML element with the ID "myID". The hash in front of "myID" tells Vue that we are addressing the element by its ID, which is similar as we tell CSS that we are addressing an element by its ID. Using $children and $parent within a Vue object will point you to the nodes before or after the current root node of the Vue element.

Manipulating Nodes

One of the core ideas of JavaScript when used for webprogramming is that we can dynamically change the content of our website without reloading it. For example, we can insert some text into an empty div:

Manipulate HTML with JavaScript (HTML)
                        
                            
Manipulate HTML with JavaScript (JS)
                        
                            document.getElementById("myID").innerHTML = "Välj en burgare";
                        
                    

In Vue, we can define "placeholder" within our HTML for dynamic content that we want to insert:

Manipulate HTML with Vue (HTML)
                        
                            
{{ arbitraryVariableName }}

Running this code will now show "{{ arbitraryVariableName }}" in the output window. Not quite what we wanted, so time to replace that. Within our Vue object, we first need to state which element in HTML we are working on again. Then, we just open a data dictionary and state which variable name is replaced by what content. This is how you do it:

Manipulate HTML with Vue (JS)
                        
                            var vm = new Vue({
                              el: '#myID',
                              data: {
                                arbitraryVariableName: 'Välj en burgare'
                              }
                            })
                        
                    
Open JSFiddle in another Browser tab so you can try around some code without loosing the progress you made so far. Use the given sample code in the new JSFiddle and try both the JavaScript and the Vue way of inserting text into your website. When you run them, you should see exactly the same result in your output window.

Of course, you can also do more complex manipulations of your HTML, like creating completely new elements and adding them to the body:

Create or Change Nodes
                        
                            // Use the createElement() method to create any HTML element
                            var btn = document.createElement('button');

                            // Use the createTextNode() method to create text content
                            var txt = document.createTextNode('Click Here');

                            // Use the appendChild() method of a node object to add one node inside another
                            btn.appendChild(txt);

                            // We can set an attribute to the element node using the setAttribute() method
                            btn.setAttribute('class', 'aButtonClass');

                            // We can also read attributes using the getAttribute() mehtod
                            console.log( btn.getAttribute('class') ); // Output: aButtonClass

                            // In order to display this newly created element, we have to append it to an existing 
                            // node in the document. In this case we add it directly to the body.
                            document.body.appendChild(btn);
                        
                    

Vue follows a different philosophy when it comes to creating nodes: Instead of dynamically creating HTML code from within JavaScript, Vue has the philosophy of pre-defining all potential concepts we need in the original HTML file and then dynamically filling it with content from withing the Vue objects. We'll see an example of how that looks a little later when we introduce conditions and loops in Vue.

Up to now, Vue only seemed to be a slightly different way of doing the same things. However, it also adds some powerful model-binding, which is one of the main advantages of using Vue over plain JavaScript. Here is a small demo example:

In your new JSFiddle, don't touch your js code for now, but change the HTML div element to contain some random text again. If you run it, you should see only your text in the output window and Vue not taking any effect. Now include the following in your div element:
Dynamic Title
                                    
                                    <div v-bind:title="arbitraryVariableName" id="myID">
                                    
                                
Run the code. What happens when you hover over your text in the output window?

To make actual use of JavaScript now, we want to add the current date to our mouse-over. To do that, simply add + new Date() after your current string you set for the arbitraryVariableName in Vue and run the code again.

What you have just observed is the power of model binding, which can be used to do a lot of neat things. If you add an input field and add two-way binding to it by using v-model, you can perhaps start imagining what can be accomplished with this feature. When you type in the input field that is generated by the below code snippet, you should be able to observe the header text changing as well.
Two-way binding
                                    
                                    <div id="myID">
                                        <input v-model="arbitraryVariableName">
                                        <h1>{{arbitraryVariableName}}</h1>
                                    </div>
                                    
                                

The difference between v-model and v-bind is that the former can only be used on common input elements but conveniently adds a v-on directive that is listening for user input.

Go back to your original JSFiddle project and create a small HTML content that contains a <div> with an ID and a headline "Välj en burgare" inside. When you run your code again, you should see the headline appearing in the output window on the bottom right.

Instead of printing the burger menu to your console, add them under your headline, but separated with some vertical space. Write this functionality both using plain JavaScript and Vue. Both should produce exactly the same HTML output when running your code.

Manipulating CSS

Through the DOM we can make style changes to HTML elements dynamically with JavaScript. This is done using the style object which is part of HTML objects provided by the DOM. So if you wish to change, for example, the colour of a paragraph you would do it by declaring document.getElementById('aParagraphID').style.color = 'green';. Almost all available CSS properties can be manipulated with the style object but remember to change any hyphenated property to camelCase. For instance, background-color becomes backgroundColor, since JavaScript would otherwise try to subtract an inferred variable color from background.

Important to understand here is that you will change the style="" attribute of the HTML element when doing this. You can also read these styles and use to assign to variables such as var col = document.getElementById('aParagraphID').style.color;. The problem here is that if you defined the style in an external CSS file, this value will be empty since it is not part of the style="" attribute of the HTML element. To access the current style in this case, we need to make use of the getComputedStyle() method available through the window object (e.g., window.getComputedStyle(element, pseudo-element);. The method takes two arguments, the first is the actual element you wish to compute the style for, and the second argument is a pseudo-element of the element (this is optional and can be replaced by null). Read more on pseudo-elements in the CSS tutorial.

As we've already discussed in the tutorial section on CSS that styling of elements should not be done within the HTML file but in the CSS file. In rare cases, using the style attribute on elements is unavoidable. However, most of the time the right approach is to dynamically add a class definition from within JavaScript and pre-define the class styling attributes in a CSS file:

Adding and Removing Class Attributes
                        
                            var myElement = document.getElementById("myID"); 
                            myElement.classList.remove("originalClass");
                            myElement.classList.add("newClass");         
                        
                    

Conditions and Loops

In JavaScript, conditions are part of the JavaScript code and very similar to the concept you know from other programming languages. If you want to make a text in HTML visible if a certain booleanExpression is true, then you could implement it in two different ways.

The first possibily is to add the text in the HTML and use the display

Conditional Statements using JS (HTML, version 1)
                        
                            
                        
                    
Conditional Statements using JS (JS, version 1)
                        
                            var myElement = document.getElementById("myID");
                            myElement.style.display = booleanExpression ? '' : 'none';
                        
                    

Another way of achieving the same functionality with plain JavaScript is by conditionally creating a new paragraph and adding it to the HTML from within JavaScript:

Conditional Statements using JS (HTML, version 2)
                        
                            
Conditional Statements using JS (JS, version 2)
                        
                            var myElement = document.getElementById("myID");
                            if (booleanExpression && !myElement.hasChildNodes())
                            {
                                myElement.innerHTML = "<p>This text is conditionally visible</p>";
                            }
                            else if (!booleanExpression)
                            {
                                myElement.innerHTML =  ""
                            }
                        
                    

Using Vue, you can add a conditional formatting directly in your HTML:

Conditional Statements using Vue
                            
                                

This text is conditionally visible

You need to bind your booleanExpression variable to some boolean expression in the data object of your Vue instance, e.g., by adding the line booleanExpression: true (don't forget to add commas to separate different fields!). Of course it is simple to just put true or false as an expression, but that is not very useful most of the time. More useful is to evaluate expressions which, for example, could be used to only display products if they are available in stock. Before we can implement this example in Vue, we first need to review how loops work.

In JavaScript, loops are again very similar to what you know from other programming languages. Here is an example of how for-loops are implemented in plain JavaScript:

Loops in JavaScript
                        
                            //simple for-loop
                            var i = 0;
                            for (i; i < 5; i++) {
                                // Do something five times
                            }

                            //for/in loop
                            for (x in object) {
                                // Do something for all elements in the array
                            } 
                        
                    

In Vue, loops (like conditions) can be part of the HTML:

Loops in Vue
                        
                           
  • If you have an array called burgers that looks as follows: [ { name: "burgerA", stock: 2 }, { name: "burgerB", stock: 0 } ], then the following code would only show the name of the one burger for which stock is greater than 0.

    Conditional Loop Example in Vue
                            
                                
    1. {{ burger.name }}

    As you can see, this can be written in a very clean and straight forward way in Vue. In JavaScript, the logic would need to happen within the JavaScript file:

    Loop Example in JavaScript (HTML)
                            
                                
    Loop Example in JavaScript (JS)
                            
                                var myElement = document.getElementById("myID");
                                for (burger in burgers)
                                {
                                    if (burger.stock > 0)
                                    {
                                        var listItem = document.createElement("li");
                                        var listValue = document.createTextNode(burger.name);
                                        listItem.appendChild(listValue);
                                        myElement.appendChild(listItem);
                                    }
                                }
                            
                        
    Take your menuItem constructor and instantiate it with at least five different items. Add your items to an menu array. Now instead of adding each element separately to your div element, use a loop to iterate through the order array and add the orders to the HTML div within your loop. If you haven't already done it, display the information about gluten and lactose as well, but only if the item contains at least one of them. Again, try to achieve the same functionality using plain JavaScript and Vue. Play around with the conditionals and loops until you feel confident that you understand what is happening.

    Document Ready?

    If you want to execute code that relates to elements in the HTML document, you have to make sure that the DOM tree has been constructed before you can make any manipulations of these elements. HTML code is parsed and run sequentially which means that any JavaScript executed from an external file will usually run before the DOM tree is fully populated. This is because the external file is placed in the <head> tag. Over the years, there have been many different strategies for handling this, e.g. by creating a function that checks if the document object is loaded and ready. Another way is adding the attribute onload="" in the <body> tag and calling a JavaScript function as the attribute value. This is, however, not recommended since we want to keep HTML and JavaScript separated.

    A more modern approach is to make use of asynchronous loading. Since you will not need to worry too much about loading time and performance in your projects, you can simply use the defer method to load scripts. By putting the keyword defer to your <script> tags in the <head> element, the linked scripts will be loaded in the background, not halting the parsing of the DOM tree, and the executed in sequence after the whole DOM tree has been loaded. Example: <script src="js/script.js" defer></script>

    Now it is finally time to get back to your code from the HTML and CSS tutorials. In order to dynamically add the burgers to your menu on the index.html page, we want to re-use the function that you wrote in JSFiddle to display your items. So first, copy your code from JSFiddle into your js_script.js and vue_script.js. Inside your HTML document, update the grid layout for your burger selection so that it is generated using JavaScript instead of being static HTML. This means you have to adapt your JavaScript code from JSFiddle to input information about your burgers into the grid layout instead of simply printing out a list. If you used a different ID for your grid layout div than in your demo HTML in JSFiddle, make sure to change the ID in your JavaScript code as well so that they match.

    If we now call the function in the script file which is included in the <head> tag of the document, we will get an error, since the div element with your ID has not yet been loaded to the DOM yet. This is an example of when we need to add the defer keyword to postpone the execution of the script. Reload the index.html document in your browser to see whether the menu items are displayed. Use the console of the browser to see if you get any error messages in case the items are not loaded properly. Make sure both the plain JavaScript and the Vue version of loading the menu dynamically works!

    JSON

    JSON is an acronym for JavaScript Object Notation and is a syntax for data exchange. It is easier to type than XML which is otherwise common to use as data exchange language. JSON text files basically just hold an anonymous JavaScript object. There are some differences to JavaScript though. For example, in JavaScript, you may use single or double quotes for strings and object key names can be defined with or without quotation marks, these are not the cases in JSON. Here you always have to use double quotes and wrap your object key names in double quotes as well.

    JSON is built on two structures: (1) objects and (2) arrays. These structures hold the data values. Valid data types for values are: a string in double quotes, a number, a boolean, or null. The value can also be an object or an array. Below is an example of a typical JSON file with structured data.

    You are almost done with loading your menu dynamically. The only thing that we still have to change is that your menu item information needs to be placed elsewhere and not be initialized within your main JavaScript or Vue code. We will use the JSON format for this. First, create a new file menu.js. Inside this, create new JSON objects for all your items. Here is how a JSON item looks like:
    Menu JSON
                                    
                                      var food = [
                                        {
                                        "name": "Ostburgare",
                                        "kCal": 850,
                                        "lactose": true,
                                        "gluten": false,    
                                        "img": "url/to/your/img"
                                        }
                                      ]
                                    
                                
    To place more menu items into your file with the JSON object, just put a comma in the second to last line between } and ] and start your new item between curly brackets again. Note that JSON has different data types - if you want to put in a number or boolean value, don't put quotation marks around the value.

    In the next step, import your menu.js file with the JSON object in your HTML file right above your other js file by putting in the <script type="text/javascript" src="menu.js"></script>. Now you can use the variable food in your JavaScript or Vue. The food variable doesn't have the return function you wrote in your own object, but apart from that, it can be used exactly like any other JavaScript object we worked with before.
    Usually, json files have the ending ".json" and start with squared bracket and not with the variable declaration like in our example. We use this as a simplification which is sufficient for the level of JavaScript we teach in this course. However, if you want to get a deeper understanding of how JavaScript works, try to create a proper json document and try to import it in a proper way to your JavaScript file.

    Events

    In HTML there are a number of actions that trigger events which you can use in order to execute functions at particular times. These events can be triggered by the user or the browser. We saw an example of this above where we added a trigger for when the document has loaded there are also triggers for when a browser window is closed or when form content has changed. With input devices we can get triggers when a user types on the keyboard, clicks or moves the mouse, or points on a touch screen. All HTML DOM Events can be found over at MDN.

    Triggering Functions Through Events
                            
                                var myButton = document.getElementbyId('myButtonID');
    
                                // In JavaScript you can either trigger an event directly on an object
                                myButton.onclick = functionName;
    
                                // Or using the event handler function
                                myButton.addEventListener("click", functionName);
    
                                // You can pass a defined function as above (no parentheses), or provide an anonymous function
                                myButton.onclick = function () {
                                    ...
                                }
                            
                        

    While JavaScript has all the necessary logic for handling events within the JavaScript file, we need to add the call of the specific function to our HTML when we add event listeners in Vue:

    Vue on:click (HTML)
                            
                                
    Vue on:click (JS)
                            
                                new Vue({
                                    el: '#orders',
                                    methods: {
                                        markDone: function() {
                                            //Add some functionality
                                        }   
                                    }
                                });
                            
                        

    First, we define which element in our HTML we are operating on. In this case, there is a <div> element with the ID orders that we are working on. Inside the "methods" part it defines exactly one method that can be called: markDone. This then defines an anonymous function in which we can define some logic to be executed when the button is clicked. Instead of defining an anonymous function within the Vue object, you can also call normal JavaScript functions outside of your Vue object.

    It's time to get some functionality to the "Order" button in your burger ordering system, so let's bring everything that we've learned together in the last task of this tutorial:
    1. Write a JavaScript event listener for your "order" button - write "Button clicked!" to the command line every time someone clicks on the button.
    2. Comment out your event listener in JavaScript for now and implement the same functionality in Vue.
    3. Write a function in JavaScript that reads the values from your text fields, radio buttons and drop-down menu and returns them in an array. Use Google to find out how you can access text field input and selected values.
    4. Call the new function that you just wrote from your Vue code and display the received order in the bottom of the customer's HTML page.
    5. Go back to where you generate the menu and change the code so that a checkbox is added to every burger on the menu.
    6. Finally, change the behavior of your button. When you click the button, the function that is called shall additionally check for all menu items if the checkbox is checked. If it is checked, the name of the burger belonging to the checkbox shall be displayed as well.
    So now your burger ordering system has already quite some functionality. Again, keep your code because we will build the last piece on top of it during the last tutorial. In that tutorial, you will learn how to use socket.io to exchange data between different clients and you will be introduced to other important parts of the project backend.

    Messaging

    The last part of this tutorial will focus on introducing the message exchange system and back-end code that is provided for your projects.

    Open localhost:3000/map in one tab of your browser and localhost:3000/dispatcher in another tab. Now click somewhere on the map in the map view and switch back to the dispatcher. What do you see?

    In the following, we will walk you through the code that achieves this communication. We start off with the sending of messages and first take a look at the HTML-part:

    Sending messages (HTML)
                            
                                
    ...

    This snippet first defines a <div> with an ID (which we will later refer back to in the Vue instance). Second, it defines what happens when one clicks on that <div>. It's the same event handling we have discussed in the 03 JavaScript part of the tutorial. That is all we need for sending a new location on the map, at least when it comes to the HTML part. Let's take a look at the Vue object that belongs to this HTML file. Here is a shortened version of the object showing only the necessary functionality to handle the actual sending of events:

    Sending messages (Vue)
                            
                               var vm = new Vue({
                                  el: '#dots',
                                  data: {
                                    orders: {},
                                  },
                                  /* Please note that there should actually be some more code here. That code is included and explained in the next example */
                                  methods: {
                                    addOrder: function (event) {
                                      socket.emit("addOrder", { orderId: this.getNext(), 
                                                                details: { x: event.clientX-10 - event.currentTarget.getBoundingClientRect().left, 
                                                                           y: event.clientX-10 - event.currentTarget.getBoundingClientRect().top, },
                                                                orderItems: ["Beans", "Curry"]
                                                              });
                                    }
                                  }
                            
                        

    This Vue instance works on the element with the ID "dots", which is exactly the outer <div> in the HTML code. It then defines an empty data object called "orders". Inside "methods:", you find the function that is called when a click on the map is registered. It defines "addOrder" as an anonymous function that calls the method socket.emit(), which sends the information specified as a parameter to the server. The first string that we send as a parameter, "addOrder", is an identifier for our back-end server to identify what type of message it is. The server matches the identifier to its declared functions (located in app.js), which enables handling messages differently depending on the identifier. For example, the server can distribute a message to all connected clients, distribute only to certain clients, or process the message's data in some way that does not include sending the message on anywhere. We'll take a closer look at how the server works towards the end of this tutorial. For now, it's enough for you to know that "addOrder" sends the order information to the server, which in turn passes it on to all connected clients. The second parameter is now a new object with all the information we actually want to send. The object starts of with a field called "orderId", which we want to be a unique identifier for the order. At the moment it's just a counter that is incremented every time this.getNext() is called. Next, it defines another object called "details" with an x and a y coordinate inside. Last, it defines an array called "orderItems". This currently always includes the two orders "Beans" and "Curry". Later, you will be asked to change this code in order to include the real order information in here. This object is now sent to all connected clients. This means that it is also sent to itself, which now brings us to the part about what happens when a message is received. Let's take another look at the same Vue object, now in its complete state:

    Receiving messages (Vue)
                            
                               var vm = new Vue({
                                  el: '#dots',
                                  data: {
                                    orders: {},
                                  },
                                  created: function () {
                                    socket.on('initialize', function (data) {
                                      this.orders = data.orders;
                                    }.bind(this));
    
                                    socket.on('currentQueue', function (data) {
                                      this.orders = data.orders;
                                    }.bind(this));
                                  },
                                  methods: {
                                    getNext: function () {
                                      var lastOrder = Object.keys(this.orders).reduce( function (last, next) {
                                        return Math.max(last, next);
                                      }, 0);
                                      return lastOrder + 1;
                                    },
                                    addOrder: function (event) {
                                      socket.emit("addOrder", { orderId: this.getNext(), 
                                                                details: { x: event.clientX-10 - event.currentTarget.getBoundingClientRect().left, 
                                                                           y: event.clientY-10 - event.currentTarget.getBoundingClientRect().top},
                                                                orderItems: ["Beans", "Curry"]
                                                              });
                                    }
                                  }
                                });
                            
                        

    The main part we have not looked at is what happens when the Vue object is created. Besides creating the variables defined in "data" and the functions defined in "methods", the anonymous function declared in "created" (the created: function () {...} part) is executed. Within this function we use socket.on() to define what should happen when we receive messages from the server. As a first parameter, it takes the type of message that is handled. In our case, we can handle "initialize" and "currentQueue" messages. It might surprise you that we don't also have "addOrder" here. This is because the server does some pre-processing with the data before it is sent to the clients. So only the server listens to "addOrder" messages and uses other message indicators when passing orders on to connected clients. In our case, the server does not only send the current order, it actually keeps track of all the orders made so far and sends the whole queue of orders every time a new order is received. The message that the server sends with this whole queue of orders has the type "currentQueue". So when we send an "addOrder" message containing our order we will practically immediately receive a "currentQueue" message from the server contaning the entire queue of orders with our own added to it. In socket.on('currentQueue', ... ) we define what to do with the received queue. In our case we have an anonymous function in which this.orders (which is the order object of the Vue instance) is assigned data.orders (which are the orders we received with the message). So we basically saved the new order queue so we can use it within our Vue instance. We do exactly the same thing when we receive an "initialize" type message, which is basically called whenever a new client connects. The idea is that a new client receives all the new order information right away, even if no new order is currently placed. The last part, .bind(this), is important. This makes the anonymous function inherit the Vue instance's scope so that this.orders doesn't refer to a hypothetical orders variable in the anonymous function. You don't have to understand in detail how this works, just remember that this is an important part of creating those socket event listeners.

    The Vue code in the JavaScript file only stores the incoming order queue in its internal Vue object. We need one more piece of code to actually display the data, and that piece sits in the HTML file:

    Receiving messages (HTML)
                            
                                
    {{key}}

    Within the outer <div> we've looked at before, there is another <div> which might look complex and confusing at first glance, but it only uses concepts we've already discussed in the tutorial: First, an enhanced for loop is used to iterate over the order object. This is the internal Vue object the order queue is stored in. For each element in the queue, we get the order (which is the order object that we've send as a message and stored in the queue) and the key. The key is the orderId again. This is again because of some processing that happens on the server side that we'll discuss later. The key is used directly between the opening and closing of the <div> element. It then uses v-bind to bind a styling element to the div. In this styling element, we access the data in the order, specifically some information that is stored in the field details within the order. From those details, we get our x and a y coordinate and add a "px" in the end to tell HTML what unit to use. Obviously, this styling adds the position of the order item and the {{key}} handles it's content, which is the number within the black circle.

    Now you have enough knowledge to start making some changes to the code. The idea is that instead of using a text field to input the address we want the customer to select the destination of the delivery on the map, and to send all the information when the customer clicks on the button on the main website. To achieve this, the following tasks have to be completed:
    1. Remove the two text fields for the address and house number input and update your JavaScript code so it does not look for this information anymore.
    2. Copy and paste the code for displaying the map from the map.html file to your index.html between the text fields and the submit-button. Ensure that it's still working by clicking on the map. Does the dispatcher view still mirror the same positions? If your clicks show up but on a different part of the page, find out how to adjust for this difference.
    Currently, the orders are sent to the dispatcher whenever a click-event on the map is registered. This is counter intuitive - what we want instead is for the customer to set the location by clicking on the map, see that the location is marked on the map and then send this with the rest of the provided information in one batch when the customer clicks on the button. This is what we will implement next:
    1. Write a new function called "displayOrder" which is triggered for click-events on the map. Instead of sending the data over the socket, the function should update the order object of the Vue function right away by not appending but overwriting what is currently in the object. This is how we ensure that a customer can only set one location. Instead of the orderID, display a "T" for "target" in the circle for the customer. Remember that we only need to store the position information at this stage - we have no information about the order-id or the orderItems. Ensure that your code is working by clicking on the map. You should now see a black circle with a "T" inside which is not visible in the dispatcher view and which changes the location when you click at the map again.
    2. Now we have to take care of the "addOrder" function. This should be triggered when we click the button. Make the appropriate change in your HTML file. Remember to change the Vue object as well: The Vue object needs to operate on the element of your button, not "dots" anymore. To make things easier, you should use the ID of one of the parents of both your map and your button and not have two separate Vue objects for these.
    3. The "addOrder" function now needs to use the position information from the "orders" object and not the "event.clientX" and "event.clientY" (because they don't exist for clicks on the button). Make the appropriate change. We don't need to listen to the server for "currentQueue" and "initialize" anymore, because we only want to submit orders one-way and not display any changes from another view. So remove the "created" part of your Vue object. Now test your code. You should see that when you make a selection on the map and click on your button that the information is correctly displayed in the dispatcher view.
    4. Instead of always ordering "Beans" and "Curry", we now want to add the name of the burger(s) that was/were actually ordered. Make the change and ensure it's working by checking the dispatcher view. For now, you should keep the names as a string array so that you do not need to make modifications to the dispatcher view yet.

    Before you can solve your last task, which is adding the information about the name, email, payment method and gender to the message you are sending, we have to take a quick look at the dispatcher view. The Vue object in dispatcher.js looks very similar to the one in deli-very.js - the only difference is that this Vue object only listens to incoming messages, it cannot send messages itself. The more interesting part is the HTML:

    Dispatcher View (HTML)
                            
                                
    #{{ key }}: {{ order.orderItems.join(", ") }}

    In addition to updating the order-information on the map, the dispatcher also sees the order-items as a lay-over on the map. All entries in the orderItems array are just concatenated using a comma. Again, a v-for is used to iterate over all items in the orders object to display all of them. So if you click your submit-button multiple times, you should see all the orders appearing in the dispatcher view.

    Your last task for this tutorial is to add the information about the customers name, email, gender and payment method to the message as well. This should logically not be part of orderItems, because it's not what the customer ordered, but personal information. So first, add a new field to the object in socket.emit() that contains an array with all the personal information and fill it with the respective entries from your form input. Then, change the dispatcher.html accordingly so the information from the new array is displayed in the dispatcher view as well. The final window for the customer should now look something like this: Screenshot of customer view after final task Screenshot of customer view after final task Screenshot of customer view after final task And the view for the dispatcher should look something like this after a few orders have been entered by customers: Screenshot of dispatch view after final task

    In the end of this tutorial, let's have a look at the app.js file. It contains the logic of the server, which you don't have to understand in detail. However, there is one part which is crucial for your projects and that is the part how the server processes and distributes incoming messages:

    Server (part 1)
                            
                               io.on('connection', function (socket) {
                                  // Send list of orders and text labels when a client connects
                                  socket.emit('initialize', { orders: data.getAllOrders() });
    
                                  // When someone orders something
                                  socket.on('addOrder', function (order) {
                                    data.addOrder(order);
                                    // send updated info to all connected clients, note the use of io instead of socket
                                    io.emit('currentQueue', { orders: data.getAllOrders() });
                                  });
    
                            });
                            
                        

    First, it is defined so that the server sends an "initialize" message whenever a new client connects. We'll take a look at what data.getAllOrders() does in a minute, but before that, let's inspect how the server handles incoming messages of the type "addOrder". It first calls a method data.addOrder() and then it sends out a message of the type "currentQueue" with the content of data.getAllOrders() again. Here you can see how the outgoing message to the client has a different type than the incoming one - this is why we listen to "currentQueue" messages in dispatcher.js and not to "addOrder". data just encapsulates an orders object to keep the global namespace clean. We could also have orders as a global object and would get the same functionality, but this coding style is a better practice of implementation.

    Server (part 2)
                            
                               Data.prototype.addOrder = function (order) {
                                  //Store the order in an object with orderId as key
                                  this.orders[order.orderId] = order;
                                };
    
                                Data.prototype.getAllOrders = function () {
                                  return this.orders;
                                };
                            
                        

    data.getAllOrders() is just a simple getter-method which returns the queue with all the orders. data.addOrder() adds a new order to the queue, but not just as is, it actually set's the orderId as a key within the orders queue. This way, we can iterate over the orders object in HTML and receive the orderId as a key as we've seen above.

    Remember that you have to upload your final mini-project to Studentportalen before February 9th at midnight. Just take the current version of your deli-very project, zip it and upload it to Studentportalen.

    In this tutorial you learned the basis about using socket.io, how the project framework looks like and how you can use it to send messages between the different views. Of course you can play around more with Vue. A good starting point is the Vue Guide. If you want some optional tasks to solve to get some more practice, here are some ideas:

    These are optional tasks to get some more practice and insight in Vue and JavaScript. They are not mandatory for you to solve and you don't have to upload this code to studentportalen (but you may, you want to, of course):
    1. If you have two different customers sending orders to the dispatcher, the orderId will overlap because it is set on the client side. This is not a scalable information, so update the code accordingly so the orderId is set on the server-side.
    2. What happens if you try to send an order without having a location set on the map? What happens if one of the fields is left blank? Fix it to give appropriate feedback to the customer and only send the order if all input is valid.
    3. Once the customer clicked on the submit-button, display the order information for the customer again under the submit-button. If there are multiple orders, all orders should be displayed in a list.
    4. Allow the dispatcher to handle orders by adding a button next to each order. If the button is clicked once, the order is in preparation. For the second click, the order is on the way. The third click resolves the order and removes it from the dispatcher view. Update the button label appropriately as well, so the dispatcher knows what a button click is doing and what the current status of the order is.
    5. Show the order status to the customer as well. When an order is resolved, it should be removed from the customer view.
    6. The dispatcher view is not really tidy right now. For example, it's difficult to see which order information belongs to which dot on the map. Ideally, the dots would be clickable and then the order and customer information would appear next to the dot. Orders from the same customer could have the same dot-color. Play around with different visualizations in the dispatcher view in order to have a more user-friendly design.