lecture at DHBW Stuttgart
given by Johannes Kronmüller in September–October 2019
Frontend Web Developer / IT-Consultant
Tim Berners-Lee, a British scientist, invented the World Wide Web (WWW) in 1989, while working at CERN.
first browser able to render embedded elements like images
The W3C’s vision was to standardize the protocols and technologies used to build the web such that the content would be available to as wide a population of the world as possible.
Obviously, this is annoying to customers actually interacting with the website…
how come those patterns are so common?
GET /images/logo.png HTTP/1.1
Host: example.com
Accept-Language: en
HTTP/1.1 200 OK
Content-Type: text/html
Request
GET / HTTP/1.1
Host: www.example.com
Response
HTTP/1.1 200 OK
Date: Mon, 23 May 2005 22:38:34 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 138
Last-Modified: Wed, 08 Jan 2003 23:11:55 GMT
Server: Apache/1.3.3.7 (Unix) (Red-Hat/Linux)
ETag: "3f80f-1b6-3e1cb03b"
Accept-Ranges: bytes
Connection: close
<html>
<head>
An Example Page
</head>
<body>
Hello World, this is a very simple HTML document.
</body>
</html>
method | semantics | Safe | Idempotent |
---|---|---|---|
GET | retrieve data | YES | YES |
HEAD | retrieve meta-information | YES | YES |
POST | create new resource | NO | NO |
PUT | replace resource | NO | YES |
DELETE | delete resource | NO | YES |
OPTIONS | retrieve supported methods | YES | YES |
PATCH | apply partial modifications | NO | NO |
status code | reason message |
---|---|
200 | OK |
301 | Moved Permanently |
304 | Not Modified |
401 | Unauthorized |
403 | Forbidden |
404 | Not Found |
500 | Internal Server Error |
standard markup language for documents designed to be displayed in a web browser
<!doctype html>
<html dir="ltr" lang="en">
<head>
My first HTML Page
</head>
<body>
Hello world!
Lorem ipsum dolor sit amet
</body>
</html>
<!doctype html>
Document Type Definition (DTD). Tells browser to use HTML5
grammatics (render mode).
<html dir=”ltr” lang=”de”>
Root element. Can hold language metadata.
<head>
Contains metadata about the page...
<meta charset="utf-8">
… used charset,
<meta name="viewport" content="width=device-width">
… render information for responsive behavior,
<title>My first HTML Page</title>
… document title.
<body>
Contains the visible part of the HTML document.
Hello World
This is a link with href attribute
The global attributes below can be used on any HTML element.
Attribute | Description |
---|---|
class | Specifies one or more classnames for an element (refers to a class in a style sheet) |
id | Specifies a unique id for an element |
style | Specifies an inline CSS style for an element |
tabindex | Specifies the tabbing order of an element |
title | Specifies extra information about an element |
See the Pen Paragraphs by Johannes (@johakr) on CodePen.
See the Pen Containers by Johannes (@johakr) on CodePen.
HTML5 introduced Semantic Elements, which clearly describe their content in a human and machine readable way.
2 main benefits
While HTML describes the content, CSS describes
CSS selectors are used to "find" (i.e. select) the HTML elements you want to style.
Simple selectors | select elements based on name, id, class |
Combination selectors | select elements based on a specific relationship between them |
Pseudo-class selectors | select elements based on a certain state |
Pseudo-elements selectors | select and style a part of an element |
Attribute selectors | select elements based on an attribute or attribute value |
class selector | .intro | Selects all elements with class="intro" |
id selector | #firstname | Selects the element with id="firstname" |
universal selector | * | Selects all elements |
element selector | p | Selects all p elements |
group selector | div, p | Selects all div and all p elements |
See the Pen Simple Selectors by Johannes (@johakr) on CodePen.
p:first-child | Selects every p element that is the first child of its parent |
p:last-child | Selects every p element that is the last child of its parent |
p:nth-child(2n) | Selects every p element that is the 2, 4, 6...th child of its parent |
input:focus | Selects inputs on focus |
a:hover | Selects links on mouse over |
:not(p) | Selects every element that is not a p element |
button:disabled | Selects every disabled button element |
See the Pen Pseudo-class Selectors by Johannes (@johakr) on CodePen.
p::after | Insert something after the content of each p element |
p::before | Insert something before the content of each p element |
p::first-letter | Selects the first letter of each p element |
p::first-line | Selects the first line of each p element |
p::selection | Selects the portion of an element that is selected by a user |
See the Pen Pseudo-elements selectors by Johannes (@johakr) on CodePen.
descendant selector |
|
Selects all p elements inside div elements |
child selector |
|
Selects all p elements where the parent is a div element |
adjacent sibling selector |
|
Selects all p elements that are placed immediately after div elements |
general sibling selector |
|
Selects every ul element that are preceded by a p element |
See the Pen Combination Selectors by Johannes (@johakr) on CodePen.
See the Pen Lobotomized Owl by Johannes (@johakr) on CodePen.
|
Selects all elements with a alt attribute |
|
Selects all elements with target="_blank" |
See the Pen Attribute selectors by Johannes (@johakr) on CodePen.
If there are multiple conflicting CSS rules that point to the same element, the browser follows some rules to determine which one is most specific.
If there are 2 rules with the same specifity, the last one wins.
That’s why it’s called cascading style sheets.
The universal selector has no specificity
* { } li { } li::first-line ul li { } ul ol+li { } h1 + *[rel=up] { } ul ol li.red { } li.red.level {} style=“” p { } div p { } div, p { } .sith { } div p.sith { } #sith { } body #darkside .sith p { }
* { } (0, 0, 0, 0) li { } (0, 0, 0, 1) li::first-line (0, 0, 0, 2) ul li { } (0, 0, 0, 2) ul ol+li { } (0, 0, 0, 3) h1 + *[rel=up] { } (0, 0, 1, 1) ul ol li.red { } (0, 0, 1, 3) li.red.level {} (0, 0, 2, 1) style=“” (1, 0, 0, 0) p { } (0, 0, 0, 1) div p { } (0, 0, 0, 2) div, p { } (0, 0, 0, 1) .sith { } (0, 0, 1, 0) div p.sith { } (0, 0, 1, 2) #sith { } (0, 1, 0, 0) body #darkside .sith p { } (0, 1, 1, 2)
ul#primary-nav li.active:not(:first-child) > a:hover::after {
content: '⧉'
}
External CSS
<head>
<link rel="stylesheet" type="text/css" href="mystyle.css">
</head>
Internal CSS
<head>
<style>
body { background-color: linen; }
</style>
</head>
Inline CSS
<body style="background-color: linen;"></body>
See the Pen CSS Properties by Johannes (@johakr) on CodePen.
See the Pen Values, Types, and Operators by Johannes (@johakr) on CodePen.
See the Pen Program Structure by Johannes (@johakr) on CodePen.
See the Pen Data Structures by Johannes (@johakr) on CodePen.
Write a program that uses console.log to print all the numbers from 1 to 100, with two exceptions. For numbers divisible by 3, print "Fizz" instead of the number, and for numbers divisible by 5 (and not 3), print "Buzz" instead.
When you have that working, modify your program to print "FizzBuzz" for numbers that are divisible by both 3 and 5 (and still print "Fizz" or "Buzz" for numbers divisible by only one of those).
(This is actually an interview question that has been claimed to weed out a significant percentage of programmer candidates. So if you solved it, your labor market value just went up.)
standard object model and programming interface for HTML
using the power of CSS selectors
// Find one (first) element matching css selector
const element = document.querySelector('#id');
// Find all elements matching css selector
const elements = document.querySelectorAll('.className');
Mutate content, attributes & styles
// Change the HTML content
document.querySelector('p').innerHTML = 'new text';
// Change any HTML attribute
document.querySelector('img').src = '/kitty.png';
document.querySelector('a').href = 'https://johakr.me';
document.querySelector('input').value = 'Jane';
// Change CSS styling
document.querySelector('p').style.color = 'red';
document.querySelector('p').style.display = 'none';
DOM Events are things that
const button = document.querySelector('button');
button.addEventListener('click', (evt) => {
// evt.target = element which received the click event
alert('YOU CLICKED THIS BUTTON', evt.target);
});
const form = document.querySelector('form');
form.addEventListener('submit', (evt) => {
// prevent default submit action
evt.preventDefault();
// get all form values as JSON
const values = Object.fromEntries(new FormData(e.target));
console.log(values);
});
Ressource Events | error, abort, load, unload |
---|---|
Focus Events | focus, blur |
Form Events | submit, reset, change, input |
View events | resize, scroll |
Keyboard events | keydown, keypress, keyup |
Mouse events | click, mouseover, mouseout |
Create a button, which displays the amount of received clicks.
{
"name": "John",
"age": 30,
"car": null,
"driverLicense": false,
"address": {
"city": "Stuttgart",
"street": "Theodor-Heuss-Straße"
},
"hobbies": ["reading", "cooking"]
}
https://jsoneditoronline.org/?id=3e0486e4b8084baca52572bff563aefa
JSON Schema is a vocabulary that allows you to annotate and validate JSON documents.
https://json-schema.org/learn/miscellaneous-examples.html
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 2,
"maxLength": 32
},
"age": {
"type": "integer",
"minimum": 0,
"maximum": 150
},
"car": {
"type": [
"string",
"null"
],
"enum": [
"mercedes",
"audi",
null
]
},
"driverLicense": {
"type": "boolean"
},
"hobbies": {
"type": "array"
}
},
"required": [
"name",
"age",
"car",
"driverLicense",
"hobbies"
]
}
https://www.jsonschemavalidator.net/
A Promise is a proxy for a value not necessarily known when the promise is created. It allows you to associate handlers with an asynchronous action’s eventual success value or failure reason. This lets asynchronous methods return values like synchronous methods: instead of immediately returning the final value, the asynchronous method returns a promise to supply the value at some point in the future.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/PromiseHey Mr. Promise! Can you run to the store down the street and get me a bottle of tequilla?
Sure thing!
While you are doing that, I will cut the lemons.
Sounds good! See you in a bit.
There are 2 promises (asynchronous actions with indefinite outcome)
with 3 possible states respectively
const cutLemons = () => new Promise((resolve, reject) => {
const success = cutting(); // doing sth async
if (success) {
resolve("🍋🍋🍋")
} else {
reject("🤕🤕🤕");
}
});
cutLemons() // pending
.then(result => console.log(lemons)) // resolved 🍋🍋🍋
.catch(error => console.log(error)) // rejected 🤕🤕🤕
In short, a Promise is an object that once called upon, will evetually resolve or reject and return a response based on some criteria that is specified within the Promise object.
The Fetch API provides an interface for fetching resources across the network...
...based on Promises.
fetch("https://swapi.co/api/people/") // request object
.then(response => response.json()) // response object
.then(json => console.log(json));
fetch("/login", {
method: "POST",
body: JSON.stringify({ username: 'john', password: 'secure' }),
headers: {
"Content-Type": "application/json"
},
}) // request object
.then(response => response.json()) // response object
.then(json => console.log(json));
A dynamic site can return different data for a URL based on information provided by the user or stored preferences and can perform other operations as part of returning a response
Your HTML gets dynamic, but who is in charge of creating the HTML markup?
HTML is completely composed on the server side
HTML Skeleton is composed on the server side & some data is
exposed by a JSON API.
Parts of the DOM are created client-side by JavaScript
Server only provides data by JSON APIs.
DOM is completely composed on the client-side by JavaScript
will help you with
Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.
Packages published to the registry must contain a package.json file.
{
"name": "04-express",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.17.1"
}
}
npm init # creates project manifest (package.json)
npm install express # installs the express web framework as a dependency
// index.js
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.json({ hello: 'world' });
});
app.listen(3000);
node index.js # runs the server
An application programming interface (API) is an interface or communication protocol between a client and a server.
REpresentational State Transfer is an architectural style for distributed hypermedia systems (web apps).
Use plural nouns, HTTP methods, status codes, JSON.
No trailing slashes, no file extensions.
Fast, unopinionated, minimalist web framework for Node.js
Routing refers to determining how an application responds to a client request to a particular endpoint, which is a URI (or path) and a specific HTTP request method (GET, POST...).
app.METHOD(PATH, HANDLER)
// GET /users
app.get('/users', (req, res) => {
// TODO: DO STUFF
});
// POST /users
app.post('/', (req, res) => {
// TODO: DO STUFF
});
The req object represents the HTTP request and has properties for the request query string, parameters, body, HTTP headers, and so on.
// GET /users/2
app.get('/users/:id', (req, res) => {
console.log(req.params.id) // access named route params
})
app.use(express.json()) // for parsing application/json
// POST /users { username: 'john' }
app.post('/users', (req, res) => {
console.log(req.body.username) // access json request body
});
// GET /users?age=26
app.get('/users', (req, res) => {
console.log(req.query.age) // access query string params
});
The res object represents the HTTP response that an Express app sends when it gets an HTTP request.
app.get('/', (req, res) => {
return res.json({ }); // send json, status code 200 implicit
});
app.get('/', (req, res) => {
return res.status(204).send(); // send 204 response with empty body
});
app.get('/', (req, res) => {
return res.status(404).json({ error: 'not found' }); // send 404 with json body
});
To serve static files such as images, CSS files, and JavaScript files, use the express.static built-in middleware function in Express.
app.use(express.static('public')) // sends static files from the public directory
OpenAPI Specification is an API description format for REST APIs. An OpenAPI file (JSON) allows you to describe your entire API, including:
{
"openapi": "3.0.0",
"info": {
"title": "Sample API",
"description": "Optional multiline or single-line description in [CommonMark](http://commonmark.org/help/) or HTML.",
"version": "0.1.9"
},
"servers": [
{
"url": "http://api.example.com/v1",
"description": "Optional server description, e.g. Main (production) server"
},
{
"url": "http://staging-api.example.com",
"description": "Optional server description, e.g. Internal staging server for testing"
}
],
"paths": {
"/users": {
"get": {
"summary": "Returns a list of users.",
"description": "Optional extended description in CommonMark or HTML.",
"responses": {
"200": {
"description": "A JSON array of user names",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
}
}
}
}
}
despite all of the language’s progress and growth, many developers have said they are dealing with JavaScript fatigue. JavaScript fatigue refers to the inability to keep up with the latest tools, the fear of becoming obsolete, the constant change of the ecosystem, and the overwhelming choice
How to Manage JavaScript Fatigue