Web Application Programming

Andrea De Lorenzo, University of Trieste

Class Schedule

Day Time Room
Monday 09:30am - 11:00am Aula V - Building G
Tuesday 03:00pm - 04:30pm Aula 4C - Building H2 bis
Wednesday 01:00pm - 02:30pm Aula 4C - Building H2 bis

http://delorenzo.inginf.units.it/

Class Format

  • In-person lectures, also recorded
  • Recordings available for about 6 months in the course Team
  • Access to the course Team via code:

2ajhwxg

Communications

Telegram Channel

https://t.me/+lRnU-qwJPP1kMGY0

Prerequisites

  • HTTP (Computer Networks)
  • Java
  • Databases

Programming Today

Some Numbers

Programming Today

Some Numbers:

  1. JavaScript
  2. Python
  3. Java
  4. PHP
  5. C#
  6. TypeScript
  7. CSS
  8. C++
  9. Ruby
  10. C

Course Program

Web Application Programming

Principles, methods, and techniques of web programming



But what does it actually mean?

Course Program

But what does it actually mean?

  • ≠ nstalling or configuring
    • Google Sites
    • Wordpress
    • Joomla
    • Drupal
    • etc.
  • ∞ Platforms and tools

Course Program

Practical Course, a lot of technologies:

Don0t use PHP
  • client side:
    • HTML, CSS, JavaScript
    • Ajax, VueJS
  • server side:
    • Node.js
    • Web Services

In practice: how to create a web application

Software

We will only use products available online, for free:

Teaching Materials

  • These slides, available on the instructor’s website
    (possibly released incrementally)
  • Additional references mentioned in the slides
    • optional
    • mandatory (→ official part of the syllabus))
  • For those who want to explore further:
    • "JavaScript Patterns", di Stoyan Stefanov
    • "JavaScript: The Good Parts", di Douglas Crockford
    • "You Don't Know JS Yet", di Kyle Simpson

Optional Teaching Materials

Programming Books:

  • "The Pragmatic Programmer: From Journeyman to Master", di Andrew Hunt
  • "Clean Code - A Handbook of Agile Software Craftsmanship", di Robert C. Martin
  • "Design Patterns", di Gamma, Helm, Johnson e Vlissides
  • "Refactoring: Improving the Design of Existing Code", di Martin Fowler

Optional Teaching Materials

Design Books:

  • "Design of everyday things", di Don Norman
  • "Designing with the Mind in Mind: Simple Guide to Understanding User Interface Design Guidelines", di Jeff Johnson
  • "Don't make me think. Un approccio di buon senso all'usabilità web e mobile", di Steve Krug
  • Seminario di Mark Miller sul design delle UI

Exam Format

  1. Final practical project (“tesina”), to be submitted three days in advance
  2. Oral exam starting with the presentation of the project

Exam Format

Some details:

  • Individual work
  • Specifications provided by the instructor
  • Specifications change at the beginning of a new course

Web Programming

WARNING!!

The technologies we will see:

Final goal: teach how to fish, rather than give the fish.

Looks simple...

Web Programming

Always evaluate:

  • How many users?
  • Required reliability?
  • Does something already exist that solves the problem?
  • Where will it reside on the server side?
  • Monolithic solution?
  • Modular solution (micro-services)?

HTML

HTML

HyperText Markup Language (HTML)

Language used to describe the content and the structure of the information in a web document

It does not describe the presentation of the information!

web page = web document

Brief History

  • Prehistory: CERN
    • 1991 → HTML (draft) first publicly available description
    • 1993 → HTML+ (draft)
    • 1995 → HTML 2.0
  • Yesterday: W3C
    • 1/1997 → HTML 3.2
    • 12/1997 → HTML 4.0
    • 2000–2001 → XHTML
  • Today: W3C + WHATWG
    • 2008–10/2014 → HTML 5 stable W3C Recommendation since October 2014
    • 12/2017 → HTML 5.2

much more complicated, actually

HTML 5 vs. HTML 4

Important enhancements:

  • one single standard, two possible syntaxes: HTML and XHTML (HTML → <!DOCTYPE html>)
  • new elements useful to make the semantics of the document more explicit: <article>, <section>, <nav>, <aside>
  • new elements useful for integrating multimedia content: <audio>, <video>

Official reference on the differences

To ensure backward compatibility, some things may be allowed for HTML interpreters but not for authors

HTML

The Basics

Very Simple HTML Document

<!DOCTYPE html>
<html>
  <head>
    <title>Hello HTML</title>
  </head>
  <body>
    <p>
      Hello <a href="http://www.units.it">UniTs</a>!<br/>
      We are learning!
    </p>
  </body>
</html>

Elements, Tags, Attributes

  • <title>Hello HTML</title>element
    • <title>start tag
    • Hello HTML → content
    • </title>end tag
  • The start tag can contain attributes:
    <a href="http://www.units.it">UniTs</a>
    • href="http://www.units.it" → attribute
    • href → attribute name
    • http://www.units.it → attribute value

Notes

  • Some elements have no content:
    • <img src="white-dog.png"/>
    • <br/>
    • there is only the start tag
  • Some attributes have no value:
    • <input type="checkbox" checked/>
  • Comments are inserted with <!--...-->:
    • <!--nobody can see this-->

Head and Body

  • <head>head, additional information about the document
  • <body> → informational content of the document

Additional Information

  • <title> → document title
  • <meta name="..." content="...">
    • name="author" → document author
    • name="description" → document description
    • name="keywords" → document keywords ("...,...,...")

From HTML to the Screen

Browser: HTML → DOM tree → screen rendering

Document Object Model (DOM)

Tree representation of the document, in memory

Alternatives to the screen:

  • speech synthesis
  • printer
  • ...

HTML

Rules

Rules

Different levels of correctness:

  • syntactic (HTML) → clear, but "it still works"
  • stylistic (HTML) → few and vague
  • stylistic (representation) → many and vague
  • semantic (HTML) → many, fairly clear

Syntactic Rules (HTML): Nesting

Elements can be nested but not overlapped

  • <p>Example <strong>correct</strong></p> → correct
  • <p>Example <strong>correct</p></strong>invalid

Syntactic Rules (HTML): Attribute Values

Attribute values must be in quotes if they contain spaces

  • <img src="white-dog.png" alt="White dog"/> → correct
  • <img src=white-dog.png alt="White dog"/> → correct
  • <img src="white-dog.png" alt=White dog/>invalid

To avoid mistakes, always use quotes!

Syntactic Rules (HTML): named character references

Special characters with a name:

  • &darr;down arrow (↓)
  • &rationals; → rationals (ℚ)
  • lots more available

Rules:

  • in the text you cannot use &s if s is the name of one of the characters
  • all named character references must end with a semicolon

Syntactic Rules (HTML):
is that all?

There are many more!

What to do?

  • consult the specification
  • use a validator

The Specification

The specification = THE manual = the bible:
HTML5 W3C Recommendation, https://html.spec.whatwg.org/multipage/

What does it contain?

  • which elements exist
  • for each element, nesting rules
  • for each element, which attributes
  • for each attribute, meaning and which values are valid
  • ...

Also as an introduction to HTML

HTML5 W3C Recommendation: extremely detailed manual

Example: start tag? end tag? />?

The start and end tags of certain normal elements can be omitted, as described later

Optional tags

complicated, better to always include the end tag

HTML5 W3C Recommendation: extremely detailed manual

Another example: <em>

The em element

Validator

W3C Validator

Validazione sito UniTS
W3C Validator at www.units.it

… the teacher is familiar with the W3C Validator

Stylistic rules (HTML)

  • Indentation!
  • ...
  • Attributes: always use quotes!
  • Close optional tags

Stylistic rules (representation)

Style → de gustibus?

Usability

Stylistic rules (representation)

Usability

10 usability crimes

they are not only about HTML (HTML ≠ representation)

HTML

HTML Elements

HTML Elements

  • <!-- --> → defines a comment
  • <!DOCTYPE> → defines the document type
  • <a> → defines a hyperlink
  • <abbr> → defines an abbreviation
  • <address> → defines an address element
  • ...

Complete list:

HTML Elements: list

Tag Description
<!--...--> Defines a comment
<!DOCTYPE>  Defines the document type
<a> Defines a hyperlink
<abbr> Defines an abbreviation or an acronym
<acronym> Not supported in HTML5. Use <abbr> instead.
Defines an acronym
<address> Defines contact information for the author/owner of a document
<applet> Not supported in HTML5. Use <embed> or <object> instead.
Defines an embedded applet
<area> Defines an area inside an image-map
<article> Defines an article
<aside> Defines content aside from the page content
<audio> Defines sound content
<b> Defines bold text
<base> Specifies the base URL/target for all relative URLs in a document
<basefont> Not supported in HTML5. Use CSS instead.
Specifies a default color, size, and font for all text in a document
<bdi> Isolates a part of text that might be formatted in a different direction from other text outside it
<bdo> Overrides the current text direction
<big> Not supported in HTML5. Use CSS instead.
Defines big text
<blockquote> Defines a section that is quoted from another source
<body> Defines the document's body
<br> Defines a single line break
<button> Defines a clickable button
<canvas> Used to draw graphics, on the fly, via scripting (usually JavaScript)
<caption> Defines a table caption
<center> Not supported in HTML5. Use CSS instead.
Defines centered text
<cite> Defines the title of a work
<code> Defines a piece of computer code
<col> Specifies column properties for each column within a <colgroup> element 
List of tags on w3schools

Sections

  • article → a piece of independent content; if nested, the inner one is related to the outer one (e.g., a blog post and its comments).
  • section → a grouping of content that is part of a broader piece of content, typically with a heading
  • nav → a section with navigation links
  • aside → a piece of content complementary to its context (e.g., notes, Twitter messages, etc.)

Sections

  • h1, ..., h6 → headings (⚠ do not use for subtitles or taglines!)
  • header → introductory content (e.g., title and navigation)
  • footer → information related to the section (e.g., author, additional links, copyright, etc.)
  • address → contact information (⚠ not for generic addresses)

Sections: questions

  • Is the font of h1 larger than that of h2?
  • Is the vertical spacing between two section elements larger than that after an article?
  • How is the address tag rendered?

Sections: questions

Wrong, you shouldn’t be asking yourself that!

HyperText Markup Language (HTML)

Language used to describe the content and structure of the information in a web document

Not the representation!

Grouping content

<h2>My memoirs</h2>
<p>
  I don’t remember them anymore...
</p>
  • p → paragraph
  • hr → topic change (not needed between sections)
  • pre → preformatted text
  • blockquote → external quotation
  • main → main content of the page, not repeated across the site. ⚠ only one per page!

Grouping content

<h3>Ingredients</h3>
<ul>
  <li>Sicilian pesto</li>
  <li>fusilli</li>
  <li>grated cheese</li>
</ul>
<h3>Preparation</h3>
<ol>
  <li>cook the pasta</li>
  <li>add the pesto</li>
  <li>garnish with cheese to taste</li>
</ol>
  • ulunordered list
  • olordered list
  • lilist item

⚠ must not be placed inside paragraphs!

Line breaks

  • CR+LF ≠ new line
  • brline break, part of the content

br elements must be used only for line breaks that are actually part of the content, as in poems or addresses.

must be used? → semantic correctness (HTML)

Textual semantics

  • em → the content of the element deserves emphasis
  • strong → the content is important
  • mark → highlighted text for reference (e.g., searched text)
  • s → the content is no longer accurate or relevant
  • sub and sup → subscript and superscript text

Textual Semantics

  • i → different reading (e.g., another language, technical term, etc.)
  • u → text with non-textual annotation (e.g., intentionally incorrect)
  • Authors are encouraged to avoid using the u element where it could be confused for a hyperlink.
  • b → draw attention
    The b element should be used as a last resort when no other element is more appropriate.

Representing Code

  • code → the content is a piece of source code
  • samp → output produced by the code
  • var → a variable
  • kbd → keyboard input... sort of
    • inside samp → the key was pressed by the user and displayed on screen
    • containing a samp tag → a menu was selected
    • containing other kbd → key combination

Example kbd

Please press Ctrl + Shift + R to reload a page.

Please press Ctrl + Shift + R to reload a page.

Example: samp in kbd

To create a new file, choose the menu option FileNew Document .

Don't forget to click the OK button to confirm once you've entered the name of the new file.

To create a new file, choose the menu option FileNew Document.

Don't forget to click the OK button to confirm once you've entered the name of the new file.

Hyperlink

I go to the <a href="http://www.units.it">university</a>
  • a → link (anchor) to another document
  • href="" → location of the other document
    • same site (relative URL) → href="udine.html"
    • different site (absolute URL) → href="http://www.units.it"
    • same document → href="#people"
    • email address → href="mailto:andrea.delorenzo@units.it"

link is something else

Images

<img src="white-dog.jpg" alt="The white dog"/>
  • src → location of the image resource
  • altfallback content: content that is to be used when the external resource cannot be used

Images: atrribute alt

Is alt mandatory?

Except where otherwise specified, the alt attribute must be specified and its value must not be empty; the value must be an appropriate replacement for the image.

One way to think of alternative text is to think about how you would read the page containing the image to someone over the phone, without mentioning that there is an image present.

In some cases, the icon is supplemental to a text label conveying the same meaning. In those cases, the alt attribute must be present but must be empty.

[...] In such cases, the alt attribute may be omitted, but one of the following conditions must be met [...]

“Almost” mandatory to include it, but it can be alt=""

Tables

<table>
  <caption>Line 36 Timetable</caption>
  <thead>
    <tr><th>Hour</th><th>Minute</th></tr>
  </thead>
  <tbody>
    <tr><td>8</td><td>00 15 30 45</td></tr>
    <tr><td>9</td><td>15 45</td></tr>
  </tbody>
</table>
  • caption → title, heading
  • thead; tfoot → column labels; totals, etc. (header, footer)
  • tbody → body (with the values)
  • tr → row (table row)
  • td, th → cell (table data/header cell)

Tables

Do not use them for formatting!

Tables must not be used as layout aids. Historically, some Web authors have misused tables in HTML as a way to control their page layout. This usage is non-conforming, because tools attempting to extract tabular data from such documents would obtain very confusing results. In particular, users of accessibility tools like screen readers are likely to find it very difficult to navigate pages with tables used for layout.

There are a variety of alternatives to using HTML tables for layout, primarily using CSS positioning and the CSS table model.

div and span

The div element has no special meaning at all. It represents its children. It can be used with the class, lang, and title attributes to mark up semantics common to a group of consecutive elements.

→ BLOCK level

The span element doesn't mean anything on its own, but can be useful when used together with the global attributes, e.g. class, lang, or dir. It represents its children.

→ inside a text line

div: example

<article lang="en-US">
  <h1>My use of language and my cats</h1>
  <p>My cat's behavior hasn't changed much since her absence, except
  that she plays her new physique to the neighbors regularly, in an
  attempt to get pets.</p>
  <div lang="en-GB">
    <p>My other cat, coloured black and white, is a sweetie. He followed
    us to the pool today, walking down the pavement with us. Yesterday
    he apparently visited our neighbours. I wonder if he recognises that
    their flat is a mirror image of ours.</p>
    <p>Hm, I just noticed that in the last paragraph I used British
    English. But I'm supposed to write in American English. So I
    shouldn't say "pavement" or "flat" or "colour"...</p>
  </div>
  <p>I should say "sidewalk" and "apartment" and "color"!</p>
</article>

span: example

<code class="lang-c"><span class="keyword">for</span> (<span class="ident">j</span> = 0; <span class="ident">j</span> &lt; 256; <span class="ident">j</span>++) {
  <span class="ident">i_t3</span> = (<span class="ident">i_t3</span> & 0x1ffff) | (<span class="ident">j</span> &lt;&lt; 17);
  <span class="ident">i_t6</span> = (((((((<span class="ident">i_t3</span> >> 3) ^ <span class="ident">i_t3</span>) >> 1) ^ <span class="ident">i_t3</span>) >> 8) ^ <span class="ident">i_t3</span>) >> 5) & 0xff;
  <span class="keyword">if</span> (<span class="ident">i_t6</span> == <span class="ident">i_t1</span>)
    <span class="keyword">break</span>;
}</code>
for (j = 0; j < 256; j++) {
i_t3 = (i_t3 & 0x1ffff) | (j << 17);
i_t6 = (((((((i_t3 >> 3) ^ i_t3) >> 1) ^ i_t3) >> 8) ^ i_t3) >> 5) & 0xff;
if (i_t6 == i_t1)
break;
}

HTML

Global Attributes

id Attribute

id → unique identifier

  • unique across the whole document
  • no spaces: <section id="abstract">

It can be used for:

  • internal links <a href="#abstract">
  • ... to be seen later

Identifiers are opaque strings. Particular meanings should not be derived from the value of the id attribute.

title Attribute

title → descriptive indication

  • <a href="udine.html" title="Info page of the neighboring city">Udine</a>
  • <abbr title="Cascading Style Sheet">CSS</abbr>

Advisory information for the element, such as would be appropriate for a tooltip.

⚠ Warning...

  • Do not consider them tooltips (e.g., on tablets?)
  • Inheritance
  • new line in HTML → actual new line!

lang and translate Attributes

lang → main language of the content

<p lang="it">L'inglese è difficile da pronunciare:
per sempio la parola <span lang="en-UK">Wednesday</span>.</p>
<p lang="de"><span lang="en-UK">Wednesday</span>
ist ein schwieriges Wort auszusprechen.</p>

translate → whether or not this content should be localized

Enumerated values:

  • yes
  • no

Example: code fragments, keyboard input, menus, etc.

class attribute

Value: a set of space-separated names:
<span class="content keyword">if</span>

Authors are encouraged to use values that describe the nature of the content, rather than values that describe the desired presentation of the content

semantic correctness (HTML)

data-* Attribute

          <section data-dog-weight="12.8kg" data-dog-speed="75%">
<h1>White dog</h1>
<p>The white dog is stocky but fast.</p>
</section>
  • what follows data- is the name of the custom attribute
  • private data for the page (or application)
  • CamelCase → camel-case (⚠ uppercase letters not allowed)

dir and style Attributes

dir → text direction

style → appearance of the element, we’ll see later

Semantic Elements – Overview

<header>
<nav>
<section><aside>
<article>
<footer>

article inside section or the other way around?

The article element specifies independent, self-contained content.

The section element defines a section in a document.

Can we use the definition to decide how to nest these elements? No.

In some HTML pages a section will contain an article, and in others an article will contain a section.

HTML Exercise 1

Write a (HTML-only) document about your city or neighborhood.

Content (items):

  • the 3 most famous people/animals
  • or, the 3 most beautiful buildings/places

We will assess the syntactic, semantic, and stylistic correctness of the HTML document.

HTML Exercise 1

Rules:

  • at least 3 items with at least 3 sections
  • use aside, i, em, strong, nav, lang, li
  • each item must include at least 500 characters of text
  • the total document must include at least 5,000 characters of text
  • include at least one internal link

Text Editor

Choose whichever you like, I suggest:

Text Editor – Visual Studio Code

Recommended extensions:

Text Editor – Sublime Text

Recommended packages:

Text Editor – Zed

Features:

  • Lightweight and very fast editor
  • Collaborative editing in real-time
  • Built-in support for multiple languages
  • Modern UI and native performance

Fewer plugins than VS Code or Sublime, but designed for speed and teamwork.

HTML Representation

Representing an HTML document

HyperText Markup Language (HTML)

Language used to describe the content and the structure of the information in a web document

The browser renders the document:
how does it draw it on the screen?

How does it draw it?

  1. HTML
  2. DOM tree
    (in-memory representation)
  3. representation on screen

How?

  • HTML → DOM tree: implicit transformation rules
  • DOM tree → screen: ...

HTML → DOM tree

HTML

<!DOCTYPE html>
<html>
 <head>
  <title>Sample page</title>
 </head>
 <body>
  <h1>Sample page</h1>
  <p>This is a <a href="demo.html">simple</a> sample.</p>
  <!-- this is a comment -->
 </body>
</html>

HTML → DOM tree

DOM tree:

  • DOCTYPE: html
  • html
    • head
      • #text: ⏎␣␣
      • title
        • #text: Sample page
      • #text: ⏎␣
    • #text: ⏎␣
    • body
      • #text: ⏎␣␣
      • h1
        • #text: Sample page
      • #text: ⏎␣␣
      • p
        • #text: This is a
        • a href="demo.html"
          • #text: simple
        • #text: sample.
      • #text: ⏎␣␣
      • #comment: this is a comment
      • #text: ⏎␣⏎

DOM tree: terminology

Let’s consider the subtree of the node body (some #text omitted):

  • the node body is the parent of the node h1
  • the nodes p, #comment, ... are sibling of the node h1
  • the nodes h1, p, ... are children of the node body
  • the nodes a, h1, p, ... are descendant of the node body
  • the nodes like body, p, h1, a are elements
  • the nodes #text are text (they have no children!)

DOM tree → screen: informally

For each node of the DOM tree:

  • what should be drawn?
  • where?
  • how?

reading the document: "drawn" → "spoken", "where" → "when"

Imagine you are the browser, or that you have to write the browser program’s code...

DOM tree → screen: formally

Goal: DOM tree → boxes tree

Main transformation rules:

  • each element E of the DOM tree may generate zero or more boxes
  • a box BE of the element E may be child of another box B'E of E or child of a box BEp of Ep, parent of E

What should be drawn?

An element is drawn if and only if all the following conditions are valid:

  • the parent has been drawn (or has no parent)
  • it is not explicitly marked as "not to be drawn"

Where should it be drawn?

Premise: types of boxes

  • block-level boxlike a paragraph
  • line boxlike a line of text
  • inline-level boxlike a word

Types of boxes: content

What they can contain:

  • block-level box
    • block-level boxes
    • line boxes
  • line box
    • inline-level boxes
  • inline-level box
    • text
    • inline-level boxes
    • block-level boxes (e.g., a list inside a strong element)

Where should it be drawn?

Roughly speaking:

  • consecutive block-level boxes are placed one below the other inside the parent block-level box

    They try to fill all the available horizontal space

  • consecutive line boxes are placed one below the other inside the parent block-level box
  • consecutive inline-level boxes are placed side by side inside the parent line-level box

    They only occupy the strictly necessary space

"consecutive" → follows the order of the DOM tree

Block-Level boxes

Non-exhaustive list:

  • p
  • table
  • nav
  • div
  • form
  • main, article, section
  • h1, h2, ...
  • ...ecc.

Inline-Level boxes

Non-exhaustive list:

  • a
  • span
  • em
  • strong
  • input, button, textarea
  • img
  • ...ecc.

Line boxes

And which elements generate Line Boxes?

They are generated automatically!

The rectangular area that contains the boxes that form a line is called a line box.

When several inline-level boxes cannot fit horizontally within a single line box, they are distributed among two or more vertically-stacked line boxes. Thus, a paragraph is a vertical stack of line boxes.

When an inline box exceeds the width of a line box, it is split into several boxes and these boxes are distributed across several line boxes. If an inline box cannot be split (e.g., if the inline box contains a single character, or language specific word breaking rules disallow a break within the inline box, or if the inline box is affected by a white-space value of nowrap or pre), then the inline box overflows the line box.

Example

DOM tree and boxes
Simplification of the transition HTML → boxes

How is it drawn?

We’re missing something:

  • given an element, what type of box does it generate?
  • given an element, how much margin does it have?
  • ...
  • "how is it drawn?"

"box type", "margin", ... → style properties of boxes

Properties and CSS

Cascading Style Sheet (CSS)

A document that specifies which values to assign to which elements’ properties

  • sheet → sheet, document
  • styleproperties related to stylistic representation
  • cascading → we’ll see...

CSS

Cascading Style Sheet (CSS)

A document that specifies which values to assign to which elements’ properties

"the element of type p must correspond to a block-level box with a 1cm margin"

HTML without CSS?

But the browser still displays my page, even though I haven’t provided any CSS!

implicit rules

The CSS rules given in these subsections are, except where otherwise specified, expected to be used as part of the user-agent level style sheet defaults for all documents that contain HTML elements.

In the specification, a CSS follows

CSS

CSS: short history

  • 1996 → CSS 1
  • 1998 → CSS 2
  • 2011 → CSS 2.1
  • (2005) → CSS 3 (still in development)
You don't need to be a programmer or a CS major to understand the CSS specifications. You don't need to be over 18 or have a Bachelor's degree. You just need to be very pedantic, very persistent, and very thorough.

CSS: basic principles

  • Compatibility: forward and backward
  • Complementary to structured documents (HTML and XML)
  • Independent from Vendor/Platform/Device (roughly, cf. printers)
  • Easy maintenance
  • Simple: only one way to achieve an effect
  • Network performance (e.g., I send formatted text instead of images)
  • Flexible: can be defined in multiple places
  • Compatible with other languages (e.g., JS)
  • Accessibility

CSS 3: the "bible"?

Less simple compared to HTML: the specification is modular

As the popularity of CSS grows, so does interest in making additions to the specification. Rather than attempting to shove dozens of updates into a single monolithic specification, it will be much easier and more efficient to be able to update individual pieces of the specification. Modules will enable CSS to be updated in a more timely and precise fashion, thus allowing for a more flexible and timely evolution of the specification as a whole.

For resource constrained devices, it may be impractical to support all of CSS. For example, an aural browser may be concerned only with aural styles, whereas a visual browser may care nothing for aural styles. In such cases, a user agent may implement a subset of CSS. Subsets of CSS are limited to combining selected CSS modules, and once a module has been chosen, all of its features must be supported.

CSS: modular specification

Development status of the specification modules

CSS: definitions

Cascading Style Sheet (CSS)

An ordered list of rules

Rule

  • selector → which elements the rule applies to
  • zero or more declarations → what applies to those elements

Declaration

  • property name
  • property value

does not apply only to HTML documents

CSS syntax

        selector {
          property-name: property-value;
          property-name: property-value;
          ...
        }

        selector { /* comment */
          property-name: property-value;
          property-name: property-value;
          ...
        }

        /* comment */

The specification defines:

  • the syntax of the selector
  • the list of property names
  • for each property, the possible values (syntax)

@ Rule

There are special rules that start with @:
  • @charset
  • @import
  • @namespace
  • @media
  • @viewport
  • ...

But we’ll talk about them later...

CSS syntax

Attention: if the syntax of a rule is incorrect, the browser must ignore the entire rule!

"must ignore" = "the specification recommends that the browser ignore it" → the browser may not ignore...

different from what happens with HTML

CSS syntax

Three levels of correctness:

  • syntactic (CSS) → otherwise it is ignored
  • stylistic (CSS) → indentation, please!
  • stylistic (representation: HTML+CSS)

there is a CSS validator

CSS location

Who defines the style?

  • Author
  • User
  • User agent

CSS location: Author

Where do I specify that I want to use certain rules for a given HTML document d? Three methods:

  • as an external text document linked to d:
    <link rel="stylesheet" type="text/css" href="...">
  • embedded in d, as the content of a style element:
    <style>...</style>
  • inside (inline) d: with only the declaration(s) as the value of a style attribute of the element I want to style (the selector is not needed!):
  • <p style="...">

CSS location: @import

The @import rule allows you to import other style sheets into a CSS code

  • It must be the first line of the CSS file
    • before it, only @charset is allowed
  • The user agent will include the file as if it were written at that point
  • Conditions can be added (e.g., device type, resolution, etc.)

Example: importing a Google Web Font

<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet" >

font-family: 'Roboto', sans-serif;

CSS

CSS Cascading

Source

Many methods...

All methods can be used together → they are all applied!

  • Multiple external documents (multiple <link ...>)

    link is also used for other purposes

  • And if multiple rules are in conflict? (rules that specify different values for the same property of one or more elements)
  • And if some property is not defined?

Inheritance

If a property P is not defined for an element E, the element inherits the value of P from its parent (parent of E)

  • For many elements and many properties, the value from the user-agent level style sheet is used

Inheritance → cascading style sheet

Inheritance: property values

How do I compute the value of each property?

Six values for each property...

  1. Declared: explicitly in the code
  2. Inherited (inherited): after applying inheritance
  3. Specified: takes the default if not declared and not inherited
  4. Computed: e.g. "2 times the font size"
  5. Used: after processing the parent (e.g. "10% width")
  6. Actual: impossible requests for the User Agent → 10.9 becomes 11

Inheritance: property values

Examples:

Declared Inherited Specified Computed Used Actual
text-align: left left left left left left
width: (none) (none) auto auto 120px 120px
font-size: 1.2em 1.2em 1.2em 14.1px 14.1px 14px
width: 80% 80% 80% 80% 354.2px 354px

em is the font size → 2em = 2 times the font size.

Inheritance: conflict

What if multiple rules are in conflict?

  1. method (origin)
    1. inline style sheet (style="...", most important)
    2. embedded style sheet (<style>)
    3. external document (<link>)
    4. user level style sheet
    5. user-agent level style sheet (least important)
  2. specificity (we’ll see)
  3. source order (the last one wins)

Inheritance: !important

CSS attempts to create a balance of power between author and user style sheets. By default, rules in an author’s style sheet override those in a user’s style sheet.

!important changes the priority:

  1. User-agent
  2. User
  3. Author

Example:

{ background-color: lightgrey !important; }

Some legitimate use cases for !important

  • You are using a Content Management System (CMS: WordPress, Drupal, ...) and cannot modify the style
  • You want to give a uniform style to the buttons of your site, so you define a generic rule. Then you add a rule with higher specificity that overrides it (we’ll see). In this case !important solves the problem

Some legitimate use cases for !important

.button {
  background-color: #8c8c8c;
  color: white;
  padding: 5px;
  border: 1px solid black;
}

#myDiv a {
  color: red;
  background-color: yellow;
}
.button {
  background-color: #8c8c8c !important;
  color: white !important;
  padding: 5px !important;
  border: 1px solid black !important;
}

#myDiv a {
  color: red;
  background-color: yellow;
}

Default values

Some keywords allow forcing certain behaviors:

  • initial → default value
  • inherit → taken from the parent element
  • ...there are others (unset, revert)

CSS

CSS selectors

Source

Selector

CSS selector

An expression that, when applied to an element, returns a boolean

fselector(E) ∈ {true, false}

The specification describes all the possible functions f

Main selectors

  • * → any element (f*(E) = true, ∀ E)
  • e → elements of type <e>
  • f e → elements of type <e> that are descendants of elements of type <f>
  • e.className → elements of type <e> with class "className"
  • e#idName → elements of type <e> whose id attribute value is equal to "idName"

descendant ≠ child

<img class="photo old" src="..."/> is selected by both img.photo and img.old

Recap: Selectors official names

Official CSS selectors names

  • *universal selector
  • etype selector (e.g., <div>, <p>)
  • .classNameclass selector
  • #idNameID selector

Combination of selectors

Selectors can be "combined":

  • e.c1 f → an <f> that is a descendant of an <e> with class "c1"
  • e f g → a <g> that is a descendant of an <f> that is a descendant of an <e>
  • e * → all descendants of an <e>

The universal selector * can be omitted in certain cases:

  • *.c1=.c1 → any element with class "c1"
  • *#id1=#id1 → any element with id "id1"

Combinators based on relationships

  • e > f → an <f> that is a child of an <e> (child combinator)
  • e + f → an <f> that is immediately preceded by its sibling <e> (adjacent sibling combinator)
  • e ~ f → an <f> that is preceded by its sibling <e> (general sibling combinator)

Attribute selectors

  • e[a] → an <e> with an attribute a
  • e[a="val"] → an <e> with attribute a equal to "val"
  • e[a~="val"] → an <e> with a="v1 v2 v3 ... val ..." (space-separated values)
  • e[a^="val"] → an <e> with a="valrest"
  • e[a$="val"] → an <e> with a="restval"
  • e[a*="val"] → an <e> with a="somethingvalsomething"
  • e[a|="val"] → an <e> with a="val-v2-v3" (values separated by "-")

    f[lang|="en"](<p lang="en-US">) = f[lang|="en"](<p lang="en-UK">) = true

Structural pseudo-classes

Pseudoclasses: classes not explicitly defined, but matching elements present in the HTML

  • e:nth-child(n), e:nth-last-child(n) → an <e> that is the n-th (n-th from the end) child of its parent
  • e:nth-of-type(n), e:nth-last-of-type(n) → an <e> that is the n-th (n-th from the end) child of its parent among children of type <e>
  • e:first-child, e:last-child, e:first-of-type, e:last-of-type
  • e:only-child, e:only-of-type → an <e> that is the only child (without siblings of type e)
  • e:root → the <e> that is the root of the document
  • e:empty → an <e> without children, not even text

nth-child: details

e:nth-child(n): n can be an expression that is a bit more complex:

  • e:nth-child(3) → the third child
  • e:nth-child(even) = e:nth-child(2n) → even children
  • e:nth-child(odd) = e:nth-child(2n+1) → odd children
  • e:nth-child(5n+2) → the 2nd, 7th, 12th, ... child

Other pseudo-classes selectors

  • e:visited, e:link → an <e> that is a link to a visited (unvisited) document (*link pseudo-classes*)
  • e:active, e:hover, e:focus → an <e> in certain states related to user interaction (*user action pseudo-classes*)
  • e:enabled, e:disabled, e:checked → an <e> that is part of the UI and in certain states (*UI element states pseudo-classes*)
  • e:lang(en) → an <e> whose content is in English (*:lang() pseudo-class*)
  • e:target → an <e> that has been targeted by an anchor (URL#anchor) (*:target pseudo-class*)

    http://units.it/bandi.html#scaduti → <section id="scaduti"> is :target

Pseudo-elements selectors

Pseudoelements: elements not explicitly defined, thus generated

  • e::first-line → a generated element representing the first line of text in an <e>
  • e::first-letter → a generated element representing the first letter of an <e>
  • e::before, e::after → a generated element inserted before (after) the content of an <e>
    • commonly used with the content property

Pseudo-elements: example

<p>Nel mezzo di cammin di nostra vita</p>

<p><span::first-letter>N</span>el mezzo di cammin di nostra vita</p>

Negation pseudo-class

  • e:not(selector) → an <e> to which the selector does not apply (only simple selectors allowed, div > div is invalid).

    p:not(:first-child) → all p elements that are not the first child of their parent

Relational pseudo-class

:has()

The :has() CSS pseudo-class represents an element if any of the selectors passed as parameters match at least one element.

  • e:has(selector) → an <e> that is the parent of an element matching the selector
  • can be chained: e:has(f):has(g) or e:has(f, g)

Support is limited to some browsers

Selectors and specificity

Remember? It is one of the mechanisms for resolving inheritance conflicts.

A "number" is generated, composed of three digits, obtained by counting in the selector:

  • ID attributes
  • other attributes or pseudo-classes
  • element names
  • pseudo-elements are ignored

The larger the number, the higher the specificity.

A great example based on Star Wars.

Selector: example

tr:nth-child(even) {
  background-color: #8be9fd; /* we’ll see... */
}
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
17 18 19 20

Selector: example

p::first-letter {
  font-size: 200%; /* we’ll see ... */
  color: #8be9fd;  /* this too ... */
}

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc tristique velit eget neque ornare, vitae luctus magna mollis. Donec arcu ligula, tristique et porttitor nec, feugiat et tortor. Suspendisse vel nisi a mauris consectetur hendrerit. Fusce congue leo est, et suscipit massa venenatis vitae. Sed nec molestie nibh. Sed purus tortor, molestie sed justo non, iaculis ultricies orci. Nullam quis quam justo. Nunc finibus aliquet tincidunt. Nunc mattis metus at arcu tristique semper. Vivamus iaculis lacus porttitor, pretium leo tincidunt, euismod nisi. Morbi sodales pharetra ante in congue. Aenean sed erat dui. Aenean eget elementum metus.

Selector: example

figure:has(figcaption) img {
    outline: 10px dashed #8be9fd;
}
With figcaption
MaLe Lab Logo
MaLe Lab Logo
Without figcaption
MaLe Lab Logo

CSS

CSS properties

We will only see a few...

A complete list

Colors

  • color → text color
  • background-color → background color
  • border-color → border color

Values:

  • color: red; → by named color keyword (including extended color keywords)
  • color: #ff0000; → hexadecimal RGB notation
  • color: rgb(255,0,0), color: rgb(100%,0%,0%) → functional RGB notation (integer and percentage values)
  • color: rgba(255,0,0,0.33), color: rgba(100%,0%,0%,0.33) → functional RGBA notation with alpha channel
  • color: transparent;transparent keyword

Backgrounds

  • background-color → background color
  • background-image → background image
  • background-repeat → background-repeat property (repeat, repeat-x, repeat-y, no-repeat)
  • background-attachment → background-attachment property (scroll, fixed, local)
  • background-position → background-position property (keywords, lengths, or percentages)
  • backgroundshorthand property for all background-related properties

Example:

body {
  background-image: url('img_tree.png');
  background-repeat: no-repeat;
  background-position: right top;
}

Fonts

  • font-family → font family name / generic family
  • font-size → absolute-size keyword | relative-size keyword | length | percentage
  • font-weight → font weight (normal, bold, 100–900)
  • font-variant → small-caps variant
  • font-style → normal | italic | oblique
  • fontshorthand property for all font-related properties

Example:

h1 {
  font-family: Helvetica, Verdana, sans-serif;
  font-weight: bold;
  font-size: x-large;
}

font-family: Helvetica, Verdana, sans-serif → the first available one is used

font-family and @font-face

The author may want to use a specific font, but it may not be installed on the user’s system:
font-family: "Fancy Design Font", sans-serif;

@font-face defines a downloadable font resource

@font-face {
  font-family: 'Ubuntu';
  src: local('Ubuntu'),
       local('Ubuntu-Regular'),
       url('http://themes.googleusercontent.com/font?kit=2Q-AW1e_taO6pHwMXcXW5w') format('truetype');
}

h1 { font: "Ubuntu" 10px;}

@font-face is an at-rule

Google Fonts

font-size

font-size: absolute-size keyword | relative-size keyword | length | percentage | inherit

Examples:

font-size: medium;     /* absolute-size keyword */
font-size: large;      /* absolute-size keyword */
font-size: 115%;       /* percentage */
font-size: larger;     /* relative-size keyword */
font-size: 10px;       /* length */
font-size: 0.75cm;     /* length */

CSS length units

Some properties accept a value of type length.

Absolute length units:

in → inches; 1in = 2.54cm
cm → centimeters
mm → millimeters
Q → quarter-millimeters (1Q = 0.25mm)
pt → points; 1pt = 1/72in
pc → picas; 1pc = 12pt
px → reference pixels (CSS pixel)

How does the browser know how many device pixels make up 1cm?

In CSS, absolute units are defined relative to the reference pixel and a standard pixel density; on many screens physical sizes are mapped heuristically.

CSS length units

Relative length units:

em → font size of the element (for font-size, relative to the parent’s font size)
ex → x-height of the element’s font
ch → width of the "0" (zero) glyph in the used font
rem → font size of the root element
lh → computed line height of the element
rlh → line height of the root element
vw → 1% of the viewport’s width
vh → 1% of the viewport’s height
vmin → 1% of the smaller viewport dimension
vmax → 1% of the larger viewport dimension

The unit px is the CSS reference pixel; it’s treated as an absolute unit in CSS specifications.

Text

  • line-height
  • letter-spacing
  • text-align
  • text-decoration
  • text-indent
  • text-transform
  • vertical-align

Examples (more here):

.draft span.note {
  text-transform: uppercase;
}
.draft span.old-version {
  text-decoration: overline;
}

Counters

They behave like variables

  • defined with the property counter-reset: counterName;
  • incremented using the property counter-increment: counterName;
  • Usable in the content property

Example:

body {
 counter-reset: sectionCount;
}
h2::before {
 counter-increment: sectionCount;
 content: "Section " counter(sectionCount) ": ";
}

CSS

CSS Layout

Source

Remember?

DOM tree and boxes
Simplification of the HTML → boxes transition

Display

Defines how the box will be rendered

  • inner display type → what formatting context it creates, and how its descendants will be positioned
  • outer display type → how the box participates in the formatting of its parent

Outer Display Type

There are three possible values

  • block
  • inline
  • run-in → merges with the block that follows it, inserting itself at its beginning (e.g., a dictionary definition).

Inner Display Type

Various options:

  • flow → depends on the Outer Display Type:
    • inline or run-in: generates an inline box
    • block: generates a block
  • flow-root → always creates a Block container
  • ... and many others (table, flex, grid, ruby)

display Property

Summarizes in a single value how to set Inner/Outer Display Type

In short, it determines the type of box that will be generated

  • display: inline → inline flow → inline-level box
  • display: block → block flow → block-level box
  • display: nonedoes not generate a box
  • display: inline-block → inline flow-root → we’ll see later
  • display: flex → block flex → we’ll see later
  • many others

display has a major impact on the representation of a document!

Hiding a box

  • visibility: visible → draws
  • visibility: hidden → does not draw

Warning:

  • visibility: hidden → the box takes up the expected space but is not visible
  • display: none → the box does not exist

Dimensions

We use width and height:

  • do not apply to inline-level boxes (as a first approximation)
  • ... and if the set dimensions exceed the window size?
    • scrollbars appear → ugly!
    • we use max-width

Dimensions

Is it enough to know width and height to calculate the occupied space?

NO!

They refer to the content; you also need to know margin and padding

Margin and padding

Dimensions

But I can cheat:

box-sizing: border-box; → padding and borders are included

Margin and padding

Hint: consider adding it in a * { } block

Positions

How can I move the box?

position property:

  • static → default, follows the normal flow; not affected by top/bottom/right/left and formally not positioned
  • relative → extra properties must be used (top, right, bottom, or left)
    • relative to itself
    • other content will not flow into the freed spaces
    • Example: position: relative; top: -20px; left: 20px; makes the second block overlap the first
      First block
      Second block

Positions

How can I move the box?

position property:

  • fixed → positioned relative to the browser window
    • managed with top, right, bottom, or left
    • the freed space is reused
    • shaky behavior on mobile devices
  • absolute → behaves like fixed but relative to the nearest positioned ancestor
    • Otherwise, it refers to <HTML>

Positions

Example:

nav {
  position: absolute;
  left: 0px;
  width: 200px;
}
section {
  /* position is static by default */
  margin-left: 200px;
}
footer {
  position: fixed;
  bottom: 0;
  left: 0;
  height: 70px;
  background-color: white;
  width: 100%;
}          
Section text 1, possibly very long.
Section text 2, possibly very long.

Floating box

A floating box is shifted in the line to the right or left until it bumps into the edge of its parent box

The rest of the content flows alongside; line boxes are shortened

  • float: left, float: right → it floats
  • float: none → does not float (default)

Ex: style="float: left; width: 200px;height: 100px;margin: 1em;"

Lorem ipsum dolor sit amet, consectetur adipiscing elit.
I’m floating!
Phasellus imperdiet, nulla et dictum interdum, nisi lorem egestas odio, vitae scelerisque enim ligula venenatis dolor. Maecenas nisl est, ultrices nec congue eget, auctor vitae massa. Fusce luctus vestibulum augue ut aliquet. Mauris ante ligula, facilisis sed ornare eu, lobortis in odio. Praesent convallis urna a lacus interdum ut hendrerit risus congue. Nunc sagittis dictum nisi, sed ullamcorper ipsum dignissim ac. In at libero sed nunc venenatis imperdiet sed ornare turpis. Donec vitae dui eget tellus gravida venenatis. Integer fringilla congue eros non fermentum. Sed dapibus pulvinar nibh tempor porta. Cras ac leo purus. Mauris quis diam velit.

Floating box

A floating box can be taller than the containing box; even the lines of the following block-level box are shortened if necessary… how to avoid this?

  • Solution 1: prevent it with clear
    • clear: left, clear: right, clear: both → don’t align with floating boxes on the left and/or right
    • clear: none → allow alignment
  • Solution 2: extend the box with a clearfix
    .clearfix {
      overflow: auto;
      zoom: 1; /* for IE6 */
    }              

float and clear: example

p {clear: left;}
        img {float: left;}
          
Float and clear
Example of float and clear

At what point in the HTML document is the image inserted?

Inline-block box

I want to create a grid of boxes that fills the entire width of the browser: I can do it with

  • float: left → inconvenient, I need to apply clear to the next block
  • display: inline-block (some issues with IE6 and IE7)
I’m an inline block!
I’m an inline block!
I’m an inline block!
I’m an inline block!
I’m an inline block!

And I don’t need any clearing!

Columns

column allows me to split text into columns

        .three-column {
  padding: 1em;
  column-count: 3;
  column-gap: 1em;
}          
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus imperdiet, nulla et dictum interdum, nisi lorem egestas odio, vitae scelerisque enim ligula venenatis dolor. Maecenas nisl est, ultrices nec congue eget, auctor vitae massa. Fusce luctus vestibulum augue ut aliquet. Mauris ante ligula, facilisis sed ornare eu, lobortis in odio. Praesent convallis urna a lacus interdum ut hendrerit risus congue. Nunc sagittis dictum nisi, sed ullamcorper ipsum dignissim ac. In at libero sed nunc venenatis imperdiet sed ornare turpis. Donec vitae dui eget tellus gravida venenatis. Integer fringilla congue eros non fermentum. Sed dapibus pulvinar nibh tempor porta. Cras ac leo purus. Mauris quis diam velit.

FlexBox

display: flex; comes with CSS3 → not all browsers handle it well

It has several properties, which can be grouped by applicability:

  • parent (container)
  • children (flex items)
container items

A visual guide

FlexBox - Container

  • flex-direction: row | row-reverse | column | column-reverse

    flex-direction2

FlexBox - Container

  • flex-direction: row | row-reverse | column | column-reverse
  • flex-wrap: nowrap (default) | wrap | wrap-reverse (bottom-top)

FlexBox - Container

  • flex-direction: row | row-reverse | column | column-reverse
  • flex-wrap: nowrap (default) | wrap | wrap-reverse (bottom-top)
  • justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly

    flex-start flex-end center space-between space-around

FlexBox - Container

  • flex-direction: row | row-reverse | column | column-reverse
  • flex-wrap: nowrap (default) | wrap | wrap-reverse (bottom-top)
  • justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly
  • align-items: flex-start | flex-end | center | baseline | stretch (aligns a flex row)
  • align-content: flex-start | flex-end | center | space-between | space-around | stretch (aligns multiple rows)

FlexBox - Children

  • order: <integer> → reorders the content
  • flex: <integer> → how to share the space
    box with flex = 1
    box with flex = 2
  • align-self: overrides the container’s value

Responsive Web Design

Simply put: we make sure our website works well on every device.

  • by rearranging the content
  • possibly using only HTML and CSS
  • JavaScript is not necessarily required
  • often designed with a 12-column grid in mind

ViewPort

The ViewPort is the area of the page visible to the user.

Smartphone & tablet browsers automatically shrink the page to fit the screen: let’s avoid this

<meta name="viewport" content="width=device-width, initial-scale=1.0">

WITHOUT specific ViewPort WITH HTML5 options for ViewPort

Differentiation by media type

You can make certain rules apply only to specific media (or media with certain characteristics):

  • using link:
    <link ... media="screen" href="css1.css">
    <link ... media="print,tty" href="css2.css">
  • using @media:
    @media print {
      /* style sheet for print goes here */
    }

Some media: screen, print, handheld, braille, speech, tty, ...

Grid Layout

We want a layout like this:

Different layouts showing the need for grid layout

How can I switch between the three layouts or create the third one?

Slides inspired by the presentation of Morten Rand-Hendriksen

Grid Layout

Terminology

  • Grid container: the element that contains a grid, set with display: grid;
  • Grid item: descendant of the grid container
  • Grid line: horizontal or vertical line delimiting the grid
    • they are numbered (double numbering: 1...N and -N...-1) Different layouts showing the need for grid layout

Grid Layout

Terminology

  • Grid container: the element that contains a grid, set with display: grid;
  • Grid item: descendant of the grid container
  • Grid line: horizontal or vertical line delimiting the grid
    • they are numbered (double numbering: 1...N and -N...-1)
  • Grid cell: like a table cell
  • Grid area: rectangular area between four lines → one or more cells
  • Grid track: space between two adjacent lines (rows and columns)
  • Grid gap: empty space between two tracks

Grid Layout

How is it used?

  1. Define a grid
  2. Place the elements in the grid

That's it!

Grid Layout

Defining the grid:

  • display: grid;
  • grid-template-columns and grid-template-rows: draw the rows; they take a list of values that specify the distances between rows.

    Units of measurement: em, px, %, fr (fractions), auto (fits content).

main{
  display: grid;
  grid-template-columns: 2fr 1fr 1fr;
}
          

Done! The grid items are placed inside (top-bottom, left-right).

Grid Layout

Spanning multiple cells

  • grid-column: x/y; → from vertical line X to Y
  • grid-row: x/y; → from horizontal line X to Y

Problem: working with numbers is tricky, it’s easy to get confused (though you can actually name the lines)

Grid Templates

Using textual descriptions to assign names to the grid container’s cells...

main{
  display: grid;
  grid-template-columns: 2fr 1fr 1fr;
  grid-template-rows: 1fr 1fr 1fr;
  grid-template-areas:
    "title title title"
    "main header header"
    "main sidebar sidebar";
}

...and in the grid items you specify the name

h1{
  grid-area: title;
}

Grid Templates

And the magic happens with media queries...

@media screen and (max-width: 700px) {
  main {
     grid-template-areas:
       "title title title"
       "header header header"
       "main main sidebar";
  }
}

Grid Layout

Some details:

  • grids can be nested without issues;
  • good support across browsers
  • ...if you’re worried, you can use @supports (grid-area: auto){...}

Grid Layout

In practice:

  1. design for mobile first (which also serves as fallback)
  2. extend with grid-templates for other resolutions

Some useful references:

CSS

CSS in different browsers

FlexBox

But does it always work?

NO!

  • CSS3 is still being written
  • several changes over time
  • the name of the property itself changes

And not only that — the problem also applies to other features (e.g., column)

Solution: prefixes

Prefixes

By specification, properties will never start with

  • "-"
  • "_"
.foo {
  display: -webkit-box;
  display: -moz-box;
  display: -ms-flexbox;
  display: -webkit-flex;
  display: flex;
  -webkit-box-orient: horizontal;
  -moz-box-orient: horizontal;
  -webkit-box-direction: normal;
  -moz-box-direction: normal;
  -webkit-flex-direction: row;
  -ms-flex-direction: row;
  flex-direction: row;
}

Tools

Do I always have to do everything manually?

No! I can get help

  • Editor-integrated tools (e.g., Emmet)
  • Online tools (e.g., AutoPrefixer)
  • Offline tools (e.g., Less)
  • Frameworks that solve the problem for me (e.g., Bootstrap)

Bootstrap

One line to rule them all, and in the darkness bind them...

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/[...]" >

Optional: some JavaScript

  • JQuery
  • Popper (popups beside elements)
  • BootstrapJS

It’s worth reading the official guide

Less

A CSS development tool written in JavaScript, usable

  • offline (command line)
  • in JS code
  • client-side (low performance, but handy for development)
    <link rel="stylesheet/less" type="text/css" href="styles.less" />
    <script src="less.js" type="text/javascript"></script> 

Less

  • Variables:
    @red: #FF0000;
    a {color: @red}

    a {color: #ff0000}

  • Nesting:
    div{
     width: 200px;
     p{ font-size: 20px; }
    }

    div{ width: 200px;}

    div p{ font-size: 20px;}

Less

  • Mixins (macros):
    .mixin{
       color: red;
       font-weight:bold;
    }
    
    p{
       font-size:18px;
       .mixin;
    }
            

    .mixin{color: red; font-weight:bold;}

    p{font-size: 18px; color: red; font-weight:bold;}

Less

  • Mixins (macros) - excluded from output:
    .mixin(){
       color: red;
       font-weight:bold;
    }
    
    p{
       font-size:18px;
       .mixin;
    }
            

    p{font-size: 18px; color: red; font-weight:bold;}

Less

  • Mixins (macros) - parametric:
    .mixin(@param){
       color: @param;
       font-weight:bold;
    }
    
    p{
       font-size:18px;
       .mixin(red);
    }

Less

  • Functions:
    • darken(color, percentage)
    • greyscale(color)
    • ...many more

CSS Exercise 1

Using the HTML document from exercise HTML-1, write CSS that renders the document like a medieval illuminated manuscript.

Example illuminated manuscript Example illuminated manuscript Example illuminated manuscript
Representation examples
  • two columns, wide borders
  • the first letter of the first text of the first section must be huge (titles excluded, the rest of the text wraps around the large letter)

CSS Exercise 1 → details

  • No/few changes to the HTML
  • Use Google Web Fonts
  • Navigation bar at the top, aligned to the right
  • If resolution is less than 800px, navbar elements must be centered
  • If resolution is less than 600px,
    • it must have only one column
    • the navigation bar must be a single column
  • If printed, it must have 3cm side margins

CSS Exercise 2

Using the HTML document again: the content of each section must be invisible by default and become visible under some user action.

For example:

  • a checkbox for the selected article
  • hovering over the element linked in the navbar
  • ...

only HTML and CSS

CSS Exercise 3

Some more changes:

  • Add contacts with email addresses and links, then
    • if the link is an email, prepend the character ✉ (\2709)
    • each address must appear in full after the link text, in parentheses
  • If displayed on a screen with resolution 600px or higher, the article must be 21 cm wide, have a white background, and appear raised above a light gray background.
  • If printed, it must have the size of an A5 with 3cm side margins and create a new page for each section@page; some help

only HTML and CSS

Web Programming browser-side

Compiled Code (or Almost)

I can ask the browser to execute compiled code (or code running on a VM)

  • ActiveX → obsolete, Windows only
  • Flash → obsolete
  • Java Applet → limited use (e.g., electronic signature with smart card)
  • WebAssembly → still experimental

Representing an HTML Document

HyperText Markup Language (HTML)

Language used to describe the content and structure of the information in a web document

In reality, the goal of HTML is explicitly broader:

This specification is limited to providing a semantic-level markup language and associated semantic-level scripting APIs for authoring accessible pages on the Web ranging from static documents to dynamic applications.

Scripting

Web Scripting

Execution of the author’s code in the context of the web document

Code? → JavaScript

... but not only

  • SVG scripting
  • TypeScript
  • GO
  • ...

Context

During execution, the code can access the DOM tree, and thus the information within the document

  • read access → retrieve elements, attributes, ... from the DOM tree
  • write access → change attributes, text, structure, ... of the DOM tree

But also external resources (the window, storage, ...)

DOM Write Access

HTML Document → DOM tree → representation

Manipulating the DOM means changing the representation — in real time!

DOM Tree and Scripting

The specification also describes the interface of the various elements:

DOM interface:

  [NamedConstructor=Image(),
   NamedConstructor=Image(in unsigned long width),
   NamedConstructor=Image(in unsigned long width, in unsigned long height)]
  interface HTMLImageElement : HTMLElement {
             attribute DOMString alt;
             attribute DOMString src;
             attribute DOMString useMap;
             attribute boolean isMap;
             attribute unsigned long width;
             attribute unsigned long height;
    readonly attribute unsigned long naturalWidth;
    readonly attribute unsigned long naturalHeight;
    readonly attribute boolean complete;
  };

This is the documentation of the DOM interface for the img element

When Is the Code Executed?

Note:

  • The HTML document is the information
  • The CSS document defines how to represent that information

→ they don’t have a specific “when”...

“When” Is the Code Executed?

It is executed when it is encountered

The browser reads (parses) the HTML document, and when it finds a script, it executes it

How to Include the Script?

Two main methods:

  • Embedded in the document:
    <script type="text/javascript">
      /* do something */
    </script>
  • As an external text file:
    <script type="text/javascript" src="..."></script>

src and Start of Execution

For external scripts, you can specify the defer attribute:

<script type="text/javascript" src="..." defer></script>

→ execution is postponed until the browser reaches the end of the document

for embedded scripts, see onload

defer or not defer?

What’s the difference?

The code can access the DOM...

HTML half-read → DOM only half-complete

Event-Driven Programming

Handler

Association of a piece of code (function) with an event

there’s a click on this button → do these things

the browser reaches the end of the document → do these things

The association can be defined:

  • in the HTML document
    <p onclick="/* piece of code */">click me!</p>
  • in the code: we’ll see later

The JavaScript Language

Introduction

What will we learn?

  • JavaScript: as a language and as a language for the Web
  • Another instance of the “programming language” problem:
    • how to give instructions to a machine with no common sense?
    • the answer is given by humans — it can be imperfect

Brief History

  • 1995: initially called Mocha, released as LiveScript by Netscape
  • 1996: Microsoft created a port called JScript (not fully compatible)
  • 1997: standardization began under Ecma as ECMAScript
  • 2011: became an ISO standard (version 5.1)
  • 2015: ECMAScript 6 (officially ECMAScript 2015)
  • 2017: version 8

Meanwhile:

  • ever-growing popularity
  • increasing use outside the browser

JavaScript Engines

Engine = pair (VM, dialect)

There are many:

  • V8 (in Chrome and Node.js)
  • SpiderMonkey (Firefox, ...)
  • Nitro / JavaScriptCore in Safari
  • ...

Sophisticated: for example, JIT

JavaScript vs Java

  • Similar (not identical) syntax, more relaxed
  • Loose typing
  • Functions are objects!
  • “Silent” exceptions
  • Imperfect, given its history

Syntax

We won’t go into detail

Some peculiarities:

  • keywords: boolean, break, delete, extends, static, ... many unused
  • semicolon: not required, but recommended
  • tolerant toward “spaces”

We’ll see more as we go

Types

5 basic immutable types:

  • numbers
  • strings
  • booleans
  • null
  • undefined

All other values are objects (mutable): arrays, functions, regexes, and objects.

Types and typeof

typeof x is a string which describe the type of x

typeof 1          // → "number"
typeof "a"        // → "string"
typeof true       // → "boolean"
typeof {a: 1}     // → "object"
typeof undefined  // → "undefined"
typeof null       // → ???

Types and typeof: null

typeof null       // → "object"!!!

But why???

In memory: 32 bits per value

  • About 3 bits for the type
    • 000 → object [Null: dato = 0x00]
    • 001 → signed int
    • 010 → double
    • 100 → string
    • 110 → boolean
  • the rest for the data

Types and typeof: null

typeof null       // → "object"!!!

Value decoding (original code):

if (JSVAL_IS_UNDEFINED(v)) {
    type = JSTYPE_UNDEFINED;
} else if (JSVAL_IS_OBJECT(v)) {
    obj = JSVAL_TO_OBJECT(v);
    if (obj [..] clasp == js_FunctionClass)) {
        type = JSTYPE_FUNCTION;
    } else {
        type = JSTYPE_OBJECT;
    }
} else if (JSVAL_IS_NUMBER(v)) {
    type = JSTYPE_NUMBER;
} else if (JSVAL_IS_STRING(v)) {
    type = JSTYPE_STRING;
} else if (JSVAL_IS_BOOLEAN(v)) {
    type = JSTYPE_BOOLEAN;
}
return type;
                  

Types and typeof

typeof x is a string that describes the type of x

typeof 1          // → "number"
typeof "a"        // → "string"
typeof true       // → "boolean"
typeof {a: 1}     // → "object"
typeof undefined  // → "undefined"
typeof null       // → "object"!!!

typeof typeof 44?

There’s a sixth possibility: we’ll see it later.

It would have been better if typeof null returned "null".

typeof and Syntax

Relaxed syntax...

Which ones work, and why?

  1. typeof 1?
  2. typeof(1)?
  3. typeof (1)?

typeof and Syntax

Relaxed syntax...

Which ones work, and why?

  1. typeof 1?
  2. typeof(1)?
  3. typeof (1)?

typeof is an operator, and what is inside the parentheses is an expression to be evaluated.

Immutable Types

Numbers, strings, and booleans are object-like: you can access their methods

(22).toExponential()   // → "2.2e+1"
"job".charAt(2)        // → "b"
true.toLocaleString()  // → "true"

but they are immutable!

Numbers

There is only one number type: float (IEEE 754 Double Precision)

Remember the issues this causes?

Numbers

There is only one number type: float (IEEE 754 Double Precision)

  • operations with decimals behave as floats:
    0.1 + 0.2 == 0.3 /* → false */
  • operations with integers are exact (really safe?)
    9999999999999999 == 10000000000000000 /* → true */

null vs undefined

An identifier refers to:

  • undefined if no value (other than undefined) has been assigned to it
  • null only if it has been explicitly assigned null

Why do both exist? Is there a reason?

  • historical reasons (exceptions came later)
  • a property that exists but has no value can be distinguished from one that doesn’t exist

Objects

An object is a mutable collection of properties.

  • Each property has a name (string) and a value (of any type)
  • Mutable:
    • Property values can be modified
    • Properties can be added or removed

Object literal

Collection of key-value couples comma-separated.

        var simba = {
          name: "simba",
          animalType: "dog",
          legs: 4,
          "sound": "bark",
          collar: {
            material: "leather",
            size: "M"
          }
        };

"animalType", "dog" is a property: "animalType" is the name (string type), "dog" is the value (string type).

The value of the property named "collar" is of type object.

var statement

var simba = {
  name: "simba",
  animalType: "dog",
  legs: 4,
  "sound": "bark"
}
  1. Defines the identifier simba as visible within the scope.
  2. Associates it with (makes it refer to) the object value.

What is the scope? We’ll see.

Accessing Object Property Values

  1. simba.name
  2. simba["name"]

Both expressions access the name property of the object referred to by simba.

The second form is necessary if the property name has certain characteristics, e.g. simba["is cute"].

If simba refers to undefined or null, then a TypeError exception is thrown.

. and [] are refinement operators.

Accessing Property Values: Syntax

Spacing is flexible:

  • simba.name
  • simba["name"]
  • simba .name
  • simba. name
  • simba . name
  • simba ["name"]
  • ...

All are equivalent and syntactically correct.

But not all are stylistically good...

Accessing Object Values

  • Read a property:
    var name = simba.name;
    If it’s not defined, the value is undefined.
  • Add/modify a property:
    simba.nickname = "White dog";
    If it’s not defined, it’s added; otherwise, it’s modified.
  • Remove a property:
    delete simba.nickname;

References

Objects are always passed by reference.

var simba = {
  name: "simba",
  collar: {
    material: "leather",
    size: "M"
  }
};
var whitedog = simba;
var c = whitedog.collar;
delete whitedog.collar;

whitedog.collar? undefined

simba.collar? undefined

c? → Object {material: "leather", size: "M"}

Iterating Over Properties: “Reflection”

var simba = {
  name: "simba",
  legs: 4
};
for (var propName in simba) {
  console.log("simba." + propName + " = " + simba[propName] + ", of type " + (typeof simba[propName]));
}

Functions

A function is an object with two additional hidden properties:

  • the code
  • the context

typeof f returns "function" if f is a function.

Here is the sixth element.

Function Literal

var sum = function(a, b) {
  var c = a + b;
  return c;
}
sum(2,3); /* → 5 */

sum refers to a function object, whose two statements (lines 2 and 3) form its body.

Function Name

var sum = function(a, b) {
  return a + b;
}
sum.name  /* → "" (or the variable name) */

Anonymous function — sum refers to the function.

This is the recommended option.

Why does it have a name property? Who added it? We’ll see.

Function Name

var sum = function summation(a, b) {
  return a + b;
}
sum.name  /* → "summation" */

Named function — sum refers to the function, summation is not a defined identifier.

The name is still useful for:

  • Debugging
  • Recursive functions

Function Name

function summation(a, b) {
  return a + b;
}
summation.name  /* → "summation" */

Named function — summation is defined and refers to the function.

Object or Function?

Functions are objects, i.e. mutable collections of properties!

var sum = function(a, b) {
  return a + b;
}
sum.p = "hello";

Scope

The scope is the region in which identifiers are defined (visible).

In JavaScript, the scope is the function body.

Despite the block syntax (curly braces), the scope is not the block!

Scope

In JavaScript, the scope is the function body.

var maxSumProd = function(a, b) {
  var s = a + b;             /* s is defined */
  var p = a * b;             /* s, p are defined */
  for (var i = 0; i < 4; i++) {
    var c = i;               /* s, p, i, c are defined */
  }
  if (s > p) {               /* s, p, i, c are defined */
    return s;
  } else {
    return p;
  }
};

Different from Java!

Scope and Hierarchy

Scopes are hierarchical: inside a function’s scope, identifiers (except for this and arguments) defined in the outer scope are visible.

var fun = function() {
  var a = 1;
  var b = 2;
  var innerFun = function() {
    var c = a + b;
    return c;
  };
  return innerFun();
};

Global Scope

var defines a variable; if omitted, it implies the global scope.

  • var a;a is defined (but uninitialized) in the local scope
  • var a = 0;a is defined and refers to 0 in the local scope
  • a = 0;
    • if a was defined in a parent scope, it now refers to 0
    • otherwise, it’s defined in the global scope and refers to 0

Global Scope

Watch out!

var calculateTopTenCosts = function() {
  var sum = 0;
  for(top = 0; top < 10; top++) {
    sum += getRankCosts(top);
  }
  return sum;
};
  • var is missing before top in the loop
  • top becomes a global variable (in a browser: the top-level window object)
  • The loop won’t execute (top is not a number)

Block Scope

var declares the variable in the function scope.

And if I want one at the block level?

Since ECMAScript 6 you can use: let

Invoking a Function

There are four Function Invocation Patterns:

  1. Method Invocation
  2. Function Invocation
  3. Apply Invocation
  4. Constructor Invocation

What changes?

  • In addition to declared parameters, each function receives two implicit ones:
    • this
    • arguments
  • this depends on the invocation pattern.

1. Method Invocation

If and only if:

  • the function is the value of an object’s property (method)
  • and it is invoked through that object’s refinement (.)
then:
  • this is the object containing it
  • arguments are the evaluations of the expressions passed in parentheses if fewer arguments are given, the missing ones are undefined

1. Method Invocation

var o = {
  n: 3,
  sum: function(m) {
    return this.n + m;
  },
  dec: function(m) {
    return n - m;
  }
};

o.sum(2)? → 5

o.dec(1)? → error! n undefined

var f = o.sum; f(2)? → NaN

var f = o.sum(); f(2)? f is not a function

Method Invocation and this

this is not optional!

given the same semantics.

2. Function Invocation

When the function is not a property of an object and is invoked directly:

var sum = add(3, 4); // sum is 7
  • The arguments: same as before.
  • this is the global object.
    • What is the global object? It depends on the environment.
    • In a browser, it’s the DOM’s window object.
    • Be careful: it’s not the this of the outer function!

2. Function Invocation

If done correctly, this would refer to the outer function...

var myObject = {
  value: 1,
  double: function() {
    var helper = function() {
      this.value = this.value * 2;
    };
    helper();
  }
}
console.log(myObject.value); /* → 1 */
myObject.double(); /* Method Invocation */
console.log(myObject.value); /* → ?? */

2. Function Invocation

Workaround

var myObject = {
  value: 1,
  double: function() {
    var that = this;
    var helper = function() {
      that.value = that.value * 2;
    };
    helper(); /* Function Invocation */
  }
}
console.log(myObject.value); /* → 1 */
myObject.double(); /* Method Invocation */
console.log(myObject.value); /* → 2 */

3. Apply Invocation

Every function also has an apply method: when called, the first parameter becomes this and the second one becomes arguments.

var sum = function(a, b) {
  return a + b;
};
sum.apply(undefined, [2, 3]); /* → 5 */

[2, 3] is an array literal — we’ll cover that later.

3. Apply Invocation

var myObject = {
  value: 1,
  double: function() {
    var helper = function() {
      this.value = this.value * 2;
    };
    helper.apply(this); /* Apply Invocation */
  }
}
console.log(myObject.value); /* → 1 */
myObject.double(); /* Method Invocation */
console.log(myObject.value); /* → 2 */

4. Constructor Invocation (new)

If a function is called with the keyword new:

  • this is a new object
  • if the return value is not an object, this is returned

The new object has a hidden link to the function’s prototype property.

4. Constructor Invocation

It looks like a constructor, but it can be misused.

By convention (and to avoid misuse), functions intended as constructors start with a capital letter.

4. Constructor Invocation

var Dog = function(name, size) {
  this.name = name;
  this.size = size;
  this.sound = "bark";
  this.makeSound = function() {
    return this.sound;
  }
};

var whiteDog = new Dog("Simba", "M");
var brownDog = new Dog("Gass", "M");

4. Constructor Invocation (Misused)

var Dog = function(name, size) {
  this.name = name;
  this.size = size;
  this.sound = "bark";
  this.makeSound = function() {
    return this.sound;
  }
};

var weirdDog = Dog("Simba", "M");
  • Value of weirdDog? undefined!

Parameters and arguments

  • arguments is a (quasi) array
    • in fact, it’s an object with a length property...
  • arguments may contain more parameters than the function definition:

    function myConcat(separator) {
      var result = '';
      var i;
      for (i = 1; i < arguments.length; i++) {
        result += arguments[i] + separator;
      }
      return result;
    }
    myConcat(', ', 'red', 'orange', 'blue');
    // → "red, orange, blue, "

Parameters and arguments

Their values are linked:

var sum = function(a, b) {
          var c = a + b;
          return c;
        }

a and arguments[0] always share the same value.

Parameters and arguments

var surpriseMe = function (a) {
  console.log(a + " - " + arguments[0]);
  a = 3;
  console.log(a + " - " + arguments[0]);
};

surpriseMe(2)?

2 - 2
3 - 3
                

Parameters and arguments

For non-strict mode functions the array index (defined in 15.4) named data properties of an arguments object whose numeric name values are less than the number of formal parameters of the corresponding function object initially share their values with the corresponding argument bindings in the function’s execution context. This means that changing the property changes the corresponding value of the argument binding and vice-versa. This correspondence is broken if such a property is deleted and then redefined or if the property is changed into an accessor property. For strict mode functions, the values of the arguments object’s properties are simply a copy of the arguments passed to the function and there is no dynamic linkage between the property values and the formal parameter values.

JavaScript oddities

but luckily there’s Stack Overflow

Default parameters

It used to be done manually:

function multiply(a, b) {
  b = typeof b !== 'undefined' ? b : 1;
  return a * b;
}

...now it can go in the signature (ECMAScript 2015)

function multiply(a, b = 1) {
  return a * b;
}

Rest parameter

Aggregates multiple parameters into an array:

function myConcat(separator, ...values) {
  var result = '';
  var i;
  for (i = 0; i < values.length; i++) {
    result += values[i] + separator;
  }
  return result;
}

myConcat(', ', 'red', 'orange', 'blue');
// → "red, orange, blue, "

Return Value

Functions always have a return value.

  • If the body contains a return statement, then (constructor invocation aside) the return value is whatever is specified there.
  • Otherwise it is undefined.

Execution (obviously) stops when the return statement is reached.

return and whitespace

The syntax of the return statement is “not very tolerant” of line breaks/whitespace

var f = function() {
  return
    {word: "hello"};
}

is equivalent to

var f = function() {
  return undefined;
    {word: "hello"};
}

...

return and whitespace

It is not equivalent to

var f = function() {
  return {word: "hello"};
}

which, in turn, is equivalent to

var f = function() {
  return {
    word: "hello"
  };
}

Scope Convention

By convention: all var statements go at the start of the body:

var fun = function() {
  var a, b, s;
  a = 1;
  b = 2;
  var innerFun = function() {
    var c;
    c = a + b;
    return c;
  }
  s = innerFun();
  return s;
};

Just a convention?

var fun = function() {
  var a = 1;
  var innerFun = function() {
    console.log(a);
  };
  innerFun();
};

fun() /* prints 1: all good */

Just a convention?

var fun = function() {
  var a = 1;
  var innerFun = function() {
    console.log(a);
    var a = 2;
  };
  innerFun();
};

fun() /* prints undefined!!! */

Why?

Variable Hoisting

Internally, JavaScript moves all var declarations to the top of the body:

var fun = function() {
  var a, innerFun;
  a = 1;
  innerFun = function() {
    var a;
    console.log(a); /* local a in scope, it’s undefined */
    a = 2;
  };
  innerFun();
};

fun() /* prints undefined */

Why?

Variable Hoisting

Why?

Because the interpreter does two passes:

For completeness, let’s mention that actually at the implementation level things are a little more complex. There are two stages of the code handling, where variables, function declarations, and formal parameters are created at the first stage, which is the stage of parsing and entering the context. In the second stage, the stage of runtime code execution, function expressions and unqualified identifiers (undeclared variables) are created. But for practical purposes, we can adopt the concept of hoisting, which is actually not defined by ECMAScript standard but is commonly used to describe the behavior.

In fact the specifications don’t say anything about “hoisting” explicitly!

Note: this does not apply to variables defined with let.

Function Hoisting

It also applies to functions, when defined directly (declarations):

function exampleOK() {
  console.log(foo); /* → function’s code */
                    /* (the function itself) */
  foo();            /* → "bar" */
  function foo() {
    console.log('bar');
  };
};

Function Hoisting

It also applies to functions, when defined directly:

function exampleNotOK() {
  console.log(foo); /* → undefined */
  foo(); /* → TypeError: foo is not a function */
  var foo = function() {
    console.log('bar2');
  };
}

Why?

  1. Only the variable foo is hoisted.
  2. The variable receives a value only at line 4.

Closure

How can we expose functionality without exposing internal variables?

Let’s take a counter:

var counter = 0;
function add() {
  counter += 1;
}
add();
add();
add();
  • Does it work? Yes
  • Does the counter increase? Yes
  • Problem: anyone who can call add() can also modify counter.

Closure

What if we put the variable inside the function?

var counter = 0;
function add() {
  var counter;
  counter += 1;
}
add();
add();
add();
  • Does it work? No, at the end counter is 0.
  • We increment an internal variable, but the global one remains visible.

Closure

What if we remove the global variable and just return the value?

function add() {
  var counter;
  counter += 1;
  return counter;
}
add();
add();
add();
  • Does it work? No, in the end counter is 1.
  • The variable is redefined at each call.

Closure

Let’s try nesting functions:

function add() {
  var counter = 0;
  function plus() { counter += 1; }
  plus();
  return counter;
}
  • In JavaScript, all functions have access to the scope in which they are defined.
  • The function plus has access to the enclosing scope, and therefore to counter.
  • Problem: how can we call plus() from outside?

Closure: the solution

A self-invoking function:

var add = (function () {
  var counter = 0;
  return function () {
    counter += 1;
    return counter;
  }
})();
add(); /* 1 */
add(); /* 2 */
add(); /* 3 */
  • Does it work? Yes, the final call returns 3.
  • Can we access counter? No.
  • But how did we do that??

Closure: the solution

var add = (function () {
  var counter = 0;
  return function () {
    counter += 1;
    return counter;
  }
})();
add(); add(); add();
  • add contains the result of a self-invoking function.
  • The self-invoking function runs once: it sets up the counter, returns a function, and is discarded.
  • add is itself a function → it has access to the scope that contains it → it can access counter, which still exists.
  • No one else can access counter.

Closure

We can also create more advanced closures:

var counter = function() {
  var n;
  n = 0;
  return {
    inc: function() {
      n = n + 1;
      return n;
    }
  };
}();
counter.inc();
  • The function referenced by inc is a closure.
  • n is an enclosed variable.

Operators + and types

Some operators also apply to unexpected types: it's useful to know how things work to avoid surprises.

Operator +:

  • if both operands are of type number, it sums the values
  • if both operands are strings, it concatenates them
  • otherwise, as we’ve already seen, it tries to convert operands to strings and concatenate them

often the source of unpleasant issues when reading a number from the DOM

Truthy and Falsy

Every value in JS also has an implicit boolean value:

Falsy
  • false
  • 0 (careful: not "0"!)
  • '' or "" (empty string)
  • null
  • undefined
  • NaN (technically: a number type value)
  • document.all (thanks to Microsoft for this one)
Truthy
...in all other cases

Truthy and Falsy

We can use a function to test it:

function truthyOrFalsy(a) {
    return a ? "truthy" : "falsy";
}
  • truthyOrFalsy(0) → falsy
  • truthyOrFalsy(10 == 5) → falsy
  • truthyOrFalsy(1) → truthy
  • truthyOrFalsy(-1) → truthy
  • truthyOrFalsy({}) → truthy

Mentiroso...

There are some values that are truthy but == false

  • "0" is truthy (non-empty string), but "0" == false:
    1. == → converts the string to a number
    2. 0 == false
    3. "0" == 0
    4. "0" == false
  • Not an isolated case...

== vs ===

Operator ===:

  • true, if operands have the same type and value
  • false, otherwise

Operator ==: tries to perform type conversion

false == undefined /* false */
false == null /* false */
null == undefined /* true */

Goodbye transitivity of equality: better === than == !

Arrays

An array is an object that:

  • has a characteristic literal syntax
  • has predefined methods

Arrays

Arrays are objects

var a = [2, 3, "pippo"];
var a = new Array(2, 3, "pippo"); /* → alternative */
a[0];     /* → 2 */
a[2];     /* → "pippo" */
a["2"];   /* → "pippo" */
a.length; /* → 3 */
a[3];     /* → undefined */

a.addedProperty = "I’m an object";
a.length; /* → 3*/

Other useful methods:

  • slice() → copies a portion of the array,
  • splice() → removes (and replaces) elements,
  • ...

Array: Length

length ≠ upper bound → I can exceed it!

var myArray = [];
myArray.length;     /*  → 0*/
myArray[10000] = "pippo";
myArray.length;     /*  → 10001*/

Adding elements:

numbers[numbers.length] = 'shi';  /*or...*/
numbers.push('go');

Array: removing elements

Assigning a smaller value to length removes the trailing elements.

You can remove any element, but it leaves a hole:

var a = [2, 3, 79];
a.length;     /* → 3 */
delete a[1];
a.length;     /* → 3 */

typeof(a[1]);    /* → "undefined" */

...better to use the splice method

Array: recognition

typeof (array) → "object"

Let’s write our own function:

var is_array = function (value) {
  return value &&
    typeof value === 'object' &&
    typeof value.length === 'number' &&
    typeof value.splice === 'function' &&
    !(value.propertyIsEnumerable('length'));
};
  • is it truthy? not {false, null, undefined, "", 0, NaN}
  • is it an object?
  • does it have a numeric length property?
  • does it have a splice function?
  • would length appear in a for ... in?

Array: sorting

Be careful...

[5, 12, 9, 2, 18, 1, 25].sort(); → [1, 12, 18, 2, 25, 5, 9]

The default behavior is to sort alphabetically!

We must specify a sorting function:

[5, 12, 9, 2, 18, 1, 25].sort(function(a, b){
    return a - b;
});

Array: iteration

Be careful...

var a = [2, 3, 79];
for (var name in a){
  console.log(name)
};
/*output: 0, 1, 2*/

We are iterating over the object’s properties, including any added manually (or by other frameworks)!

Array: iteration

We should use the old-fashioned way:

var a = [2, 3, 79];
for (var i = 0; i < a.length; i += 1) {
  console.log(a[i]);
}
/*output: 2, 3, 79*/

Or use the forEach method:

a.forEach(function(value){
  console.log(value);
});
/*output: 2, 3, 79*/

Memoization

Sometimes I need to reuse already computed results...

var fibonacci = function (n) {
  if (n < 2){
    return n
  } else {
    return fibonacci(n - 1) + fibonacci(n - 2);
  }
};

for (var i = 0; i <= 10; i += 1) {
  console.log('// ' + i + ': ' + fibonacci(i));
}

Inefficient: function called 453 times

Memoization

Let’s use a closure to store previously computed results:

var fibonacci = (function() {
  var memo = [0, 1];
  var fib = function (n) {
    var result = memo[n];
    if (typeof result !== 'number') {
      result = fib(n - 1) + fib(n - 2);
      memo[n] = result;
    }
    return result;
  };
  return fib;
})();

Nice! fibonacci called only 18 times

Class-Based Inheritance

Traditionally (Java, C++, C#) there are two entities: classes and instances.

  • Class: defines the properties and methods of the object it describes, but never represents one. Example: Teacher
  • Instance: materialization of a class. Example: Alberto Bartoli, Eric Medvet, Andrea De Lorenzo

In addition:

  • properties and constructor are defined separately;
  • hierarchy is defined through subclassing an existing class;
  • explicit casting is not required (polymorphism).

Prototype-based Inheritance

JavaScript is loosely-typed: every object derives from another object from which it inherits properties, called its prototype.

How is this achieved?

  • Every constructor function has a prototype property containing the object to be used as prototype in a constructor invocation

    in fact, this property exists in every function; a function becomes a constructor when it is invoked with new

  • The new object has a hidden link to the value of the constructor function’s prototype property: __proto__

Delegation

  • Access for adding/modifying/removing properties uses the hidden link
  • Read access:
    • if the property exists in the object, its value is returned
    • otherwise, if it exists in the prototype, that value is returned
    • otherwise, if it exists in the prototype’s prototype, ...
    • ...
    • otherwise, undefined
  • Write access:
    • creates a new property in the final object → the prototype is not modified.

Example of Prototype-based Inheritance

public class Employee {
   public String name;
   public String dept;
   public Employee () {
      this("", "general");
   }
   public Employee (String name) {
      this(name, "general");
   }
   public Employee (String name, String dept) {
      this.name = name;
      this.dept = dept;
   }
}
function Employee(name="", dept="general") {
  this.name = name;
  this.dept = dept;
}

Example of Prototype-based Inheritance

public class Engineer extends Employee {
  public String machine;
  public Engineer () {
    this("");
  }
  public Engineer (String mach) {
    dept = "engineering";
    machine = mach;
  }
}
function Engineer(mach = "") {
  this.dept = 'engineering';
  this.machine = mach;
}
Engineer.prototype = new Employee;

Example of Prototype-based Inheritance

function Employee(name="", dept="general") {
  this.name = name;
  this.dept = dept;
}
function Engineer(mach = "") {
  this.dept = 'engineering';
  this.machine = mach;
}
Engineer.prototype = new Employee;
var luca = new Engineer("computer");

What are the values of the following expressions:

  • luca.machine → "computer"
  • luca.dept → "engineering"
  • luca.name → ""

Dynamic Inheritance

An object’s prototype is itself an object, so if you

  • add
  • modify
  • remove

a property to/from the prototype, this affects all objects that have that prototype (through delegation).

...
Engineer.prototype = new Employee;
var luca = new Engineer("computer");
Employee.prototype.salary = 100;
luca.salary; /* → 100*/

The Creating Function

  • Creating an object as a literal is equivalent to creating it with a constructor invocation of Object
  • Creating a function as a literal is equivalent to creating it with a constructor invocation of Function

The Creating Function: Objects

Creating an object as a literal is equivalent to creating it with a constructor invocation of Object

var o = new Object();

is equivalent to

var o = {};

and the object can be filled later.

Object.prototype is the prototype object from which both derive.

Literal creation is recommended

The Creating Function: Objects

For example, I can add read-only properties:

var o = new Object();
Object.defineProperty(o, "prop", {
    value: "test",
    writable: false
});

o.prop; /* → "test"*/
o.prop = "Ciao";
o.prop; /* → "test"*/

The Creating Function: Functions

Creating a function as a literal is equivalent to creating it with a constructor invocation of Function

var f = new Function();

is equivalent to

var f = function(){};

but the function cannot be filled later (in its body).

Function.prototype is the object from which both derive (the prototype).

Literal creation is necessary

Dynamic Inheritance

var sum = function(a, b) {
  return a+b;
};
sum.creator;  /* → undefined*/

Function.prototype.creator = "Eric Medvet";

sum.creator;  /* → Eric Medvet (delegation)*/
var prod = function(a, b) {
  return a*b;
}

prod.creator; /* → Eric Medvet (delegation)*/
prod.creator = "Simba";
prod.creator; /* → Simba (no delegation)*/
sum.creator;  /* → Eric Medvet*/

Setting the Prototype

Object.create = function(o) {
  var F = function () {};
  F.prototype = o;
  return new F();
};

var dog = {sound: "bark"};
var coloredDog = Object.create(dog);
coloredDog.sound; /* → bark*/

Setting the Prototype

Object.create = function(o) {
  var F = function () {};
  F.prototype = o;
  return new F();
};
  1. creates a new function and adds it as a property of Object
  2. when create is invoked with argument o
    1. creates a new empty function F
    2. sets its prototype to o
    3. returns the result of new F() (a new object with a hidden link to the prototype property of the creating function, that is o)

Augmenting

Object.create = function(o) {
  ...
};
  1. creates a new function and adds it as a property of Object

Augmenting a base type (Object)

This can also be done with strings, numbers, etc...

String.reverse = function() {
  ...
};

don’t overuse it

Monkey Patching

Adding new functionality to the system library by extending it

Example: we want to add a function to String that capitalizes the first letter

String.prototype.capitalize = function() {
  return this[0].toUpperCase() + this.substr(1);
}
const capitalName = 'jacob'.capitalize(); /* → "Jacob" */

Monkey Patching

It should be avoided!

If other libraries do the same thing, what would happen?

This problem has already occurred in the past: smooshgate

The MooTools library, widely used at the time, had added the flatten function

Array.prototype.flatten = function(){...}

...but in 2019, flatten was introduced into ECMAScript!

Dynamic Inheritance and Primitives

Object.prototype.version = "7.2.11";
"uh".version; /* → 7.2.11*/

Why? Isn’t "uh" a primitive String?

Primitives Coercion

typeof true; /*"boolean"*/
typeof Boolean(true); /*"boolean"*/
typeof new Boolean(true); /*"object"*/
typeof (new Boolean(true)).valueOf(); /*"boolean"*/

typeof "abc"; /*"string"*/
typeof String("abc"); /*"string"*/
typeof new String("abc"); /*"object"*/
typeof (new String("abc")).valueOf(); /*"string"*/

typeof 123; /*"number"*/
typeof Number(123); /*"number"*/
typeof new Number(123); /*"object"*/
typeof (new Number(123)).valueOf(); /*"number"*/

To execute "uh".version, a new String object (wrapper) is created, used only to access the property, and then discarded by the Garbage Collector.

Primitives Coercion

So, can I add properties to primitives?

var primitive = "september";
primitive.vowels = 3;
primitive.vowels; /* → ??*/

Primitives Coercion

So, can I add properties to primitives? NO!

var primitive = "september";
primitive.vowels = 3; /* → create a new wrapper:*/
(new String("september")).vowels = 3;
primitive.vowels;     /*→ create a new wrapper to
                        read the property:*/
(new String("september")).vowels; /* → undefined*/

Primitives Un-Wrapping

Wrappers easily revert to their primitive type:

var Twelve = new Number(12);
var fifteen = Twelve + 3;
fifteen; /*15*/
typeof fifteen; /*"number" (primitive)*/
typeof Twelve; /*"object"; (still object)*/

But it’s still JavaScript:

if (new Boolean(false)) {
  console.log("true");
} else{
  console.log("false");
}

Output?

Primitives Un-Wrapping

Wrappers easily revert to their primitive type:

var Twelve = new Number(12);
var fifteen = Twelve + 3;
fifteen; /*15*/
typeof fifteen; /*"number" (primitive)*/
typeof Twelve; /*"object" (still object)*/

But it’s still JavaScript:

if (new Boolean(false)) {
  console.log("true");
} else{
  console.log("false");
}

Output? → "true", because objects are truthy.

For booleans, use the value: new Boolean(false).valueOf();

Exercise: JS-WordCounter

Create a JavaScript function wordCounter that returns a <word, frequency> "map" computed from the input string.

wordCounter("la mamma di mio figlio è anche mamma di mia figlia"); /* → <"mamma", 2/11>, <"figlio", 1/11>, ...*/

see String.split()

And what if there are punctuation marks? See regular expressions and their literal syntax.

Exercise: JS-Infinite Function

Create a JavaScript function such that:


var f = ...;
f(1)                  /* → 1*/
f()(3)                /* → 3*/
f()()()()("a")        /* → "a"*/
f()...()("x")         /* → "x"*/

var g = f;
f = 33;
g()()()()(f)          /* → 33*/

JavaScript

JavaScript in the Web Context

DOM

Remember?

Document Object Model (DOM)

Tree representation of the document, in memory

Programmatic interface for:

  • Accessing the tree
  • Modifying the structure
  • Modifying the style
  • Modifying the content
Essentially, it connects web pages to scripts or programming languages.

DOM Interfaces

  • Node: provides what’s needed for the tree representation
  • Document: derives from Node, but some properties don’t apply (e.g., a Document has no attributes).
  • Browser:
    • Window: the browser window (or tab) containing the document

      Note: some methods always apply to the window (e.g., window.resizeTo)

    • Navigator: information about the browser
    • History: navigate forward/backward in the browsing history
    • ...

DOM Interfaces - HTML

  • HTMLDocument: extends Document, but with HTML5 many methods/properties are already included in it.
  • HTMLElement: for all types
    • HTMLAnchorElement
    • HTMLParagraphElement
    • HTMLFormElement
    • etc.

Not just HTML! There’s also the entire world of SVG...

Accessing Elements

The document object contains the DOM:

  • document.getElementById("...") → returns the element (HTMLElement) with the specified ID
  • document.getElementsByTagName("...") → returns the elements with the specified tag name ("a", "span", ...); "*" returns all of them
  • document.getElementsByClassName("...") → returns the elements with the specified class (a list of space-separated values)
  • document.querySelectorAll("...") → returns all elements matching the given CSS selector
  • document.querySelector("...") → returns the first element matching the given CSS selector

Creating Elements

  • document.createElement("...") → creates an element of the specified type
  • element.appendChild(child) → adds the element as the last child of the specified element node
  • .innerHTML → reads/sets the HTML code that defines the element’s descendants
var mainSection = document.getElementById("mainSection");
var newP = document.createElement("p");
newP.innerHTML = "this is the <b>new</b> paragraph";
mainSection.appendChild(newP);

Styling Elements

  • element.style → accesses the element’s style attribute → ignores inherited/external styles
    element.style.color = "#ff3300";
    element.style.marginTop = "30px";
  • window.getComputedStyle(element) → returns the computed style for the element

DOM Event Model

There are several ways to bind to events:

  1. HTML Attribute
<button onclick="alert('Hello world!')">

Ugly:

  • Heavier markup → less readable
  • Content and behavior not separated → bugs harder to find

DOM Event Model

There are several ways to bind to events:

  1. HTML Attribute
  2. EventTarget.addEventListener (specifications)
/* Assume myButton is a Button */
myButton.addEventListener('click', function(){
  alert('Hello world');
}, false);

Nice!

Note: not supported in Internet Explorer 6–8, where EventTarget.attachEvent is used instead → it's better to use libraries for maximum compatibility.

DOM Event Model

There are several ways to bind to events:

  1. HTML Attribute
  2. EventTarget.addEventListener (specifications)
  3. DOM element properties
/* Assume myButton is a Button */
myButton.onclick = function(event){
  alert('Hello world');
};

Note: only one handler per element per event.

Event Propagation

There are three phases:

  1. Capture: the event propagates from the most ancestral target (Window) down to the most specific one (e.g., td)
  2. Target: the event reaches its destination and, depending on the event type, either stops or continues with bubble
  3. Bubble: the event propagates back up the tree

Manually stop bubbling propagation:

ev.stopPropagation();

Note: this does not stop the function’s execution.

Exercise: JS-Anagrams

Write an HTML document with an input box and a button: when the user clicks the button, the page shows a list with the first 20 permutations of the word typed into the box.

Hints:

  • input box → input
  • "when the user" → event

ECMAScript 2015

a.k.a. ES6

Some ES6 Features

We’ve already seen some basics:

  • const – use by default
  • let – use if the value may change
  • Default parameter value: function a(par1 = 1){...

String Concatenation

Old style:

let name = "Luca";
console.log("Hi " + name + ", how are you?");

ES6: backticks and interpolation!

let name = "Luca";
console.log(`Hi ${name}, how are you?`)

Implicit Properties

Old style:

function createProduct(price, quantity){
    return {
        price: price,
        quantity: quantity
    };
};

ES6: shorter syntax

function createProduct(price, quantity){
    return {
        price,
        quantity
    };
};

Object Destructuring

Old style:

var product = {
    descr: "computer",
    price: 10
};
var price = product.price;
var descr = product.descr;

ES6:

const product = {
    descr: "computer",
    price: 10
};
const {price, descr} = product;

Arrow Functions

Anonymous functions with benefits:

  • shorter syntax
  • no own this

Old style:

var x = function(params){...}

ES6:

const x = (params) => {...}
  • () optional with one parameter (not with 0 or more)
  • If single statement → {} optional (implicit return)

Classes

We know how to use constructor invocation...

function Person(name, age){
  this.name = name;
  this.age = age;
};

var luca = new Person("Luca", 21);

...and we know how inheritance works (though it’s awkward)

Classes

ES6 solution: class

class XYZ{
  constructor(par1, ...){
    this.par1 = par1;
  }
}

Important notes:

  • It’s actually a function with a special literal syntax
  • It does NOT undergo hoisting

Alternative syntax:

var XYZ = class {...}
var XYZ = class XYZ {...}

Classes

Constructor

→ a special method, valid only inside a class, that creates an instance of it

  • A constructor cannot be a getter, setter, or async
  • A class can have only one constructor!

Classes

Inheritance

class X extends Y{
  constructor(par1, par2, ...){
    super(par1);
    ...
  }
}

Voilà!!

Classes

Inheritance

You can extend any constructor function that has a prototype property

function OldStyle() {
  this.someProperty = 1;
}
OldStyle.prototype.someMethod = function () {};

class Modern extends OldStyle {}

class Modern {
  someProperty = 1;
  someMethod() {}
}

class AnotherClass extends Modern {}

Classes

Public Fields

class ClassWithFields {
  instanceField;
  instanceFieldWithInitializer = "instance field";
  static staticField;
  static staticFieldWithInitializer = "static field";

  constructor(instanceField) {
    this.instanceField = instanceField;
  }
}

Classes

Private Fields

Declared using the # prefix

class ClassWithPrivateFields {
  #privateField;
  #privateFieldWithInitializer = 42;

  #privateMethod() { }

  static #privateStaticField;
  static #privateStaticFieldWithInitializer = 42;

  constructor(x) {
    this.#privateField = x;
  }
}

Promise

Premise: setTimeout(), setInterval()

  • They take two parameters: code and an optional delay
  • They execute code after delay milliseconds (0 if not specified)
    • setInterval() repeats the operation

Promise

Premise: asynchronous operations

setTimeout(function(){
  console.log("Delayed for 5 seconds.");
}, 5000);
console.log("Hello!");
  • setTimeout() is asynchronous
  • It prints "Hello!" first, then after 5 seconds "Delayed for 5 seconds."

Promise

...that is, managing asynchronous operations.

"When you’re done sending the message, let me know — but let me keep working meanwhile..."

Before: a custom design pattern to solve the problem

function sendMessage(msg, callback){
    function doAsync(){
      /* asynchronous operation */
      let success = contactServerAndSendData(msg);
      callback(success);
    };
    doAsync();
}
sendMessage("Pippo", function(result){
  console.log(result);
});

Promise

...that is, managing asynchronous operations.

"When you’re done sending the message, let me know — but let me keep working meanwhile..."

Before: a design pattern to handle this

ES6: Promise — a built-in object representing the completion (or failure) of an async operation.

var promiseObj = new Promise(executorFunction);

executorFunction: a function run by the constructor with two parameters:

  • resolveFunc → runs if everything goes well
  • rejectFunc → runs if an error occurs

This function performs the asynchronous operation.

Promise

...that is, managing asynchronous operations.

"When you’re done sending the message, let me know — but let me keep working meanwhile..."

Before: a design pattern to handle this

ES6: Promise — a built-in object representing the completion (or failure) of an async operation.

var promiseObj = new Promise(executorFunction);
promiseObj.then(
  /* function executed if everything goes well */
).catch(
  /* function executed if an error occurs */
);

Promise

  • Executor: a function performing a time-consuming operation
  • Consumer: a function that needs the result from the producer

Promise: executor

The executor function takes two parameters — two callbacks for success and failure.

  • resolve(value) → called if the operation completes successfully, with value as the result
  • reject(error) → called if an error occurs, passing error
let promise = new Promise(function(resolve, reject) {
  /* executor: time-consuming operation */
  resolve("Done!"); /* completes and returns "Done!" */
});

Promise: consumer

The executor is not run until the Promise is explicitly invoked by a consumer.

  • then(): takes two functions — one for success, one for failure
  • catch(): takes one function to handle errors
let promise = new Promise(function(resolve, reject) {
  /* executor: time-consuming operation */
  resolve("Done!");
});

promise.then(
  function(result){ console.log(result) },
  function(error){ console.log(error) } /* optional */
);

Promise: consumer

We can rewrite everything using arrow functions:

let promise = new Promise((resolve, reject) => {
  /* executor: time-consuming operation */
  resolve("Done!");
});

promise.then(
  result => console.log(result),
  error => console.log(error) /* optional */
);

Promise: asynchronous

let promise = new Promise(function(resolve, reject) {
  setTimeout(() => resolve("Done!"), 2000)
});

promise.then(result => console.log(result));
console.log("Hello");

Prints "Hello" first, then "Done!"

Promise: chaining

function setTimeoutPromise(delay) {
  return new Promise((resolve, reject) => {
    if (delay < 0) return reject("No delay");
    setTimeout(() => {
      resolve(`You waited ${delay} milliseconds`);
    }, delay);
  });
}
setTimeoutPromise(250).then(msg => {
  console.log(msg);
  return setTimeoutPromise(500);
}).then(msg => {
  console.log(msg);
});

Modules

Once upon a time, everything worked fine:

  • Simple web pages (little CSS)
  • Occasional bits of JavaScript

Now:

  • JavaScript everywhere
  • Heavy and complex JavaScript
  • Hard to manage in a single .JS file (concurrent edits?)

“It would be nice to split code into multiple, easy-to-maintain files...”

Modules

You can probably guess the name of the solution ↑

Browser support is quite good — if we pretend IE doesn’t exist...

Two keywords:

  • export → exports something from a JS file
  • import → imports something into a JS file

Modules — Export

Option 1: at the bottom of the file

  • export default something; → exports “something” as default
  • export {foo, bar}; → exports “foo” and “bar”

Option 2: inline (nicer)

export default class Something {...}
export function foo(){...}
export function bar(){...}

Only one default export per file

Modules — Import

Import the default export:

import Something from './module.js';
let x = new Something();

Import the rest:

import Something, {foo, bar} from './module.js';
let x = new Something();

Alias for non-default imports:

import {foo as funkyFoo} from './module.js';

Aliases help resolve name conflicts across modules

To module or not to module?

When including a script in HTML, you can use several attributes:

  • defer → runs after the DOM is loaded
  • nomodule → script ignored if the browser supports modules (ES6) → fallback for older browsers
  • type="module" → runs only if the browser supports modules:
    • enables module support
    • implies defer
    • if async is added, runs immediately

"use strict"

Introduced with ES5, still valid in ES6 and later.

Forces a stricter interpretation of JavaScript.

  • Prevents some common mistakes
  • Throws more exceptions instead of silently failing
  • Improves security and performance
"use strict";
x = 10; /*  Error! x is not declared */

Without "use strict", that line would silently create a global variable.

"use strict" — Effects

  • No implicit globals — variables must be declared with let, const or var
  • No deleting variables or functions
  • No duplicate parameter names
  • this in functions not bound to objects is undefined (not window)
  • Reserved words (e.g. implements, package) cannot be used as identifiers
function test(){
  "use strict";
  console.log(this); /* undefined */
}
test();

Always a good idea in modern JS — or use ES modules, which are strict by default.

"use strict" — Examples

"use strict";

/* 1. No implicit globals */
x = 3.14;        /* ReferenceError */

/* 2. No deleting variables or functions */
var a = 1;
delete a;        /* SyntaxError */

/* 3. No duplicate parameters */
function f(x, x) { }  /* SyntaxError */

"use strict" — Examples

"use strict";

/* 4. 'this' not bound to window */
function show() {
  console.log(this);  /* undefined */
}
show();

/* 5. Reserved words */
var private = 1;  /* SyntaxError */

ES6 modules are strict by default — no need for "use strict".

Asynchronous JavaScript

JavaScript

JavaScript is a single-threaded, non-blocking, asynchronous, concurrent programming language with lots of flexibility

  • Single-thread?
  • Asynchronous?

Synchronous JavaScript Execution Stack

JavaScript maintains a stack in memory called the function execution stack, which keeps track of the currently executing function.

  • When a function is invoked, it is pushed onto the execution stack
  • If that function calls another one, the new function is added to the top and executed
  • When a function finishes, it is popped off the stack and control returns to the previous one
  • This continues until the stack becomes empty

Function Execution Stack: example

function f1(){
  ...
}
function f2(){
  ...
}
function f3(){
  ...
}
f1();
f2();
f3();
f1()f2()f3()

Function Execution Stack

Function Execution Stack: example

function f1(){
  ...
}
function f2(){
  f1();
}
function f3(){
  f2();
}
f3();
f1()
f2()
f3()

Function Execution Stack

Asynchronous JavaScript

Some functions may finish “later”: I can have a function with a set delay, or one whose result depends on something external (data from a server, a database query, ...).

In these situations, I don’t want to block the execution of the code, but rather continue running other functions.

There are two main types of operations that are executed asynchronously (non-blocking):

  • Browser APIs / Web APIs: DOM events such as clicks, scrolling, and similar actions, as well as methods like setTimeout()
  • Promises: objects that allow asynchronous operations to be executed

Browser API/Web API

function printme() { /* callback */
  console.log('print me');
}

function test() {
  console.log('test');
}

setTimeout(printme, 2000);
test();

In what order are the two sentences printed?

  • Are 2 seconds waited before stampami() and then test() are executed?
  • Or is test() executed first, and after 2 seconds stampami()?

Browser API/Web API

JavaScript has a dedicated queue for callbacks (Callback Queue)

A loop is created that periodically checks the queue and moves callbacks to the stack (Event Loop):

  • Functions in the stack are executed normally
  • If a browser API is invoked, a callback is added to the queue (macrotask)
  • If the stack is empty, the callback is moved from the queue to the stack
  • Then it starts over

Browser API/Web API: example

function f1() {
    console.log('f1');
}

function f2() {
    console.log('f2');
}

function main() {
    console.log('main');
    setTimeout(f1, 0);
    f2();
}
main();
console.log('f2')
f2() setTimeout() console.log('main') console.log('f1')
main() f1()

Function Execution Stack

API => f1()

Browser API

f1()

Callback Queue

Promise

  • Promises are objects that allow asynchronous code execution
  • To handle Promises, a separate queue is used (Job Queue)
  • A function in the Job Queue is called a microtask
  • If there are elements in both the Callback Queue and the Job Queue, the Event Loop executes those in the Job Queue (microtasks) first

Promise: example

function f1() {
  console.log('f1');
}

function f2() {
  console.log('f2');
}

function main() {
  console.log('main');
  setTimeout(f1, 0);
  new Promise((resolve, reject) =>
      resolve('promise')
  ).then(resolve => console.log(resolve))
  f2();
}

main();
console.log('f2')
f2() setTimeout() console.log('main') console.log('f1') console.log('promise')
main() f1() anonymous

Function Execution Stack

API => f1()

Browser API

f1()

Callback Queue

anonymous

Job Queue

async functions

With ECMAScript 2017, support was added for writing asynchronous functions — another way to handle Promises.

An asynchronous function is a function that:

  • Is declared with the async keyword
  • Allows the use of the await keyword inside it
  • Returns a Promise
async function hello() { return "Hello!"; }
hello(); /* returns a Promise */

async functions

They can be written in a more elegant form

let hello = async function() { return "Hello!"; };

Or using an arrow function

let hello = async () => "Hello!";

async functions

To consume the Promise, you can use then()

hello().then((value) => console.log(value));

Or use the shorthand version

hello().then(console.log);

await

The advantages of asynchronous functions become clear when combined with the await keyword:

  • it can be placed before a Promise
  • it can be placed before an asynchronous function
  • it can only be used inside an asynchronous function
  • it pauses the code until the Promise is resolved, then returns its resolved value
async function hello() {
  return await Promise.resolve("Hello");
};

hello().then(console.log);

Example of an asynchronous function

function after2sec() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('Done!');
    }, 2000);
  });
}

async function asincrona() {
  console.log('Exec and await');
  const result = await after2sec();
  console.log(result);
}
asincrona();

Concatenate

function setTimeoutPromise(delay) {
  return new Promise((resolve, reject) => {
    if (delay < 0) return reject("No delay")
    setTimeout(() => {
      resolve(`You waited for ${delay} milliseconds`);
    }, delay);
  })
}
asincrona();

async function asincrona() {
  const msg1 = await setTimeoutPromise(250)
  console.log(msg1)
  const msg2 = await setTimeoutPromise(500)
  console.log(msg2)
}

Errors Handler

With promises:

setTimeoutPromise(-10).then(msg => {
  console.log(msg);
}).catch(error => {
  console.error(error)
}).finally(() => {
  console.log("Exec anyway!");
});

With async code:

asincrona();
async function asincrona() {
  try {
    const msg = await setTimeoutPromise(-10);
    console.log(msg);
  } catch (error) {
    console.error(error);
  } finally {
    console.log("Exec anyway!");
  }
}

JavaScript

Ajax

Classic Web

When you enter a URL in the browser:

  • The computer resolves the IP address using DNS
  • The browser connects to that IP and requests the specified file
  • The web server (e.g., Apache) accesses the file system and returns the content

Some URLs invoke programs executed by the web server, passing parameters:

http://www.sailing.org/16937.php?meetid=82
  • Server: www.sailing.org
  • Program: 16937.php
  • Parameters: meetid=82

Classic Web

Sequence diagram of a web application without Ajax
Sequence diagram of a non-Ajax web application (source)

Classic Web

Changing data === reloading the page

  • Each request blocks the user interface until it’s completed
  • The entire page must always be reloaded
  • Poor user experience: the visual context is lost
  • Validation often happens only on submission (e.g., username already exists)

But we want to build Web Applications — that is, websites that behave much more like desktop applications.

Interactive Web

Sequence diagram of a web application with Ajax
Sequence diagram of a web application with Ajax (source)

Ajax

Ajax

Asynchronous JavaScript + XML: a way of using JavaScript to enrich an HTML document with new information (without reloading it)

Ajax is the key to interactivity in Web Applications!

  • Asynchronous
  • JavaScript
  • XML → the new information is in this format

In practice: Ajax = using the JavaScript object XMLHttpRequest

Ajax in practice: XMLHttpRequest

The XMLHttpRequest specification defines an API that provides scripted client functionality for transferring data between a client and a server.

It’s not a programming language, but a way of using JavaScript.

Specification available at http://www.w3.org/TR/XMLHttpRequest, documentation on w3schools

as of today, specification ≠ implementations

Ajax in practice: XMLHttpRequest

  1. prepare the object
  2. send the request
  3. when the response arrives, use it

"Use it" ≈ read it and update the DOM with the new information

Preparing and Sending

var xhr = new XMLHttpRequest();
xhr.onreadystatechange = myFunction;
xhr.open("GET", url, true);
xhr.send(null);

You need to tell the XMLHttpRequest object:

  • urlwho to contact
  • myFunction → what to do when the response is received
  • The boolean parameter in open specifies that the request is asynchronous

Reading the Response

"When the response arrives"...

  • xhr.onreadystatechangehandler, the function invoked on every state change
  • xhr.readyStatestate of the interaction (between the object and the server):
    • 0 → object just created (after new ...)
    • 1 → ready (after open())
    • 2 → response headers received (after send())
    • 3 → loading (downloading the response payload)
    • 4 → response received (or error)

    Usually, we’re only interested in state 4.

Reading the Response

When it’s available (readyState == 4) and no errors occurred, the response is found in:

  • xhr.responseText → response body as a string
  • xhr.responseXML → response body as a Document object, only if:
    • the HTTP response body was a valid XML document
    • the MIME type received is null or of XML type (text/xml, application/xml, ...)

Which one should you use? It depends!

Reading the Response as Text

xhr.onreadystatechange = function() {
  var text;
  if (xhr.readyState == 4) {
    if (xhr.status == 200) {
      text = xhr.responseText;
      /* use text in the DOM */
    } else {
      /* handle the error */
    }
  }
};

Reading the Response as Text

Some options:

  • The server returns plain text or an HTML fragment:
    document.getElementById("toRewrite").innerHTML = xhr.responseText;
  • The server returns formatted text (e.g., one,two,three):
    var listEl = document.getElementById("list");
    var pieces = xhr.responseText.split(",");
    var i, newLi;
    for (i = 0; i < pieces.length; i++) {
      newLi = document.createElement("li");
      newLi.innerHTML = pieces[i];
      listEl.appendChild(newLi);
    }

Reading the Response: XML

<?xml version="1.0" encoding="UTF-8"?>
<animals>
  <animal type="dog">
    <name>Simba</name>
    <color>white</color>
  </animal>
  <animal type="dog">
    <name>Gass</name>
    <color>brown</color>
  </animal>
</animals>

A concise introduction to XML can be found at w3schools

Reading the Response: XML

var xmlDoc = xhr.responseXML;
var animals = xmlDoc.getElementsByTagName("animal");
var i, name, nameEl;
for (var i = 0; i < animals.length; i++) {
  var nameEl = animals[i].getElementsByTagName("name")[0];
  var name = nameEl.childNodes[0].nodeValue;
  ...
}

Note: it’s possible to convert XML into an object.

Reading the Response: JSON

Do we always have to use XML to communicate? NO!

JavaScript Object Notation

A standard for transmitting data in a readable format, made up of attribute–value pairs and ordered lists of values.

Derived from JavaScript’s Object Literal syntax:

{ "employees": [
    {"firstName":"Mick","lastName":"Jagger"},
    {"firstName":"Ronnie","lastName":"Wood"},
    {"firstName":"Keith","lastName":"Richards"},
    {"firstName":"Charlie","lastName":"Watts"} ]
}
  • more compact
  • easier to manipulate in JavaScript

Reading the Response: JSON

JSON.parse() takes care of everything:

xhr.onreadystatechange = function() {
  var obj;
  if (xhr.readyState == 4) {
    if (xhr.status == 200) {
      obj = JSON.parse(xhr.responseText);
      /* use obj in the DOM */
    } else {
      /* handle the error */
    }
  }
};

Same Origin Policy

Same Origin Policy

Restriction that prevents a script from communicating with servers different from the one that hosts the document it originates from.

The script on www.trieste.it/index.html cannot do xhr.open("GET", "http://udine.it", true)

JS–Ajax Exercise

Create (at least) 3 files (JSON or XML or text), each containing a profile for an animal. Each profile has at least 3 attributes (for example: name, color, ...).

Create an HTML document with a text box. When the user types the animal’s name, the document updates with a table containing the data for the requested animal, if available.

In Chrome, there’s a restriction that prevents loading documents via the file:/// protocol.

When loading documents via the file:/// protocol in Firefox, the values of xhr.status are not the usual HTTP ones.

Use the embedded web servers in VS Code or Atom.

fetch()

Using XMLHttpRequest is cumbersome:

  • designed in 2006, for older versions of JavaScript
  • it’s asynchronous code: you might use Promises or async
  • → the fetch function was introduced more recently

fetch(): example

Inspired by jQuery’s ajax(), but:

  • the promise is not rejected on an HTTP error status
  • by default it does not send cookies to other URLs
  • it uses the Response and Request objects
fetch('url')
.then(response => response.json())
.then(data => console.log(data));

fetch(): example

async function postData(url = '', data = {}) {
  const response = await fetch(url, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(data) 
  });
  return response.json(); 
}

postData('https://example', { data: 'xxx' })
  .then(data => {
    console.log(data); 
  });

Web Server (1)

HTTP: Overview

Hyper Text Transfer Protocol - RFC 2616

  • Transmission of information on the Web
    • Not necessarily via TCP
  • Request/Response
  • Connection closed as soon as possible
    • With HTTP/1.1 (1999): one connection for multiple requests
    • Pros: fewer active connections
    • Cons: implicitly stateless

HTTP: Request

Three sections per request:

  1. Request line
    • Method
    • URI
    • Protocol version
  2. Header: optional?
    • Mandatory with HTTP/1.1: HOST
    • End of header: <CR><LF>
  3. Body
    • Not all requests require it
GET /index.html HTTP/1.1
Host: www.example.com
<CR><LF>

HTTP: Request Header

Key-value pairs, one per line

  • Accept: acceptable content types in the response
    • Also: accept-language, accept-encoding (compression), accept-charset, ...
  • User-agent: program making the request
  • Host: DNS name of the server being contacted
  • Cookies
  • Authorization
  • Connection management
  • Cache, proxy management, ...

HTTP: Authentication

Handled in the Request Headers

Basic:

  1. Request the page
  2. Response: unauthorized + authentication info, e.g. Realm = "Esse3 Credentials"
  3. The browser asks the user for credentials
  4. Request the page again, including username:password in the header
    Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

Warning:

  • BASE64 encoding → plain text!!
  • Better used only with HTTPS

HTTP: Authentication

Handled in the Request Headers

Digest (RFC-2617):

  1. Request the page
  2. Response: unauthorized + authentication info
    WWW-Authenticate: Digest realm="testrealm@host.com", nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093"
  3. The browser asks the user for credentials
  4. Request the page again, including in the header
    Authorization: Digest username="Mufasa", ..., MD5(MD5(username:realm:password):nonce)

HTTP: Logout

The browser stores credentials to avoid asking every time: how do I log out?

Not supported!

  • ... one could send intentionally wrong credentials (not all browsers support this)
  • ... logout() JavaScript function (not supported)

In short: the logout problem arises ⇛ use a session-based authentication system

HTTP: Request Method

  • GET:
    • requests the representation of a resource
    • does not modify the content
    • empty body
  • HEAD:
    • same as GET, but does not return the response body (e.g., for cache validation)
  • POST:
    • adds data to an existing entity → identified by the URI
    • creates a new resource not yet identified → handled by the target URI
    • the entity to be added is contained in the body
  • PUT:
    • saves the entity contained in the body at the specified URI
    • if it already exists: overwrites it; otherwise: creates a new one
  • PATCH:
    • partial modification of a resource (RFC-5789)
  • DELETE:
    • removes the identified entity

HTTP: Response

Three sections per response:

  1. Status line
    • 1xx Informational
    • 2xx Successful
    • 3xx Redirection
    • 4xx Client error
    • 5xx Server error
  2. Header
    • Server: type and version
    • Content-Type
    • Set-Cookie
    • ..., cache control, ETag, etc.
  3. Body

HTTP: Response

HTTP/1.0 200 OK
Date: Mon, 28 Jun 2004 10:47:31 GMT
Server: Apache/1.3.29 (Unix) PHP/4.3.4
X-Powered-By: PHP/4.3.4
Vary: Accept-Encoding,Cookie
Cache-Control: private, s-maxage=0,
max-age=0, must-revalidate
Content-Language: it
Content-Type: text/html; charset=utf-8
Age: 7673
X-Cache: HIT from wikipedia.org
Connection: close

Web Server

Application that handles web page transfer requests via the HTTP or HTTPS protocol

  • Apache
  • MS IIS
  • nginx
  • LiteSpeed

Apache

  • Created in 1995
  • Part of the Apache Foundation since 1999 (first software project)
  • Countless tutorials available
  • Manual exceeding 500 pages
  • Extensible through modules
  • Configuration file based
  • Typical LAMP installation:
    • Linux
    • Apache
    • MySQL
    • PHP

Apache: Concurrency Management

Multi-Processing Modules: when Apache was created, HTTP keep-alive connections did not exist

  • Process (pre-fork):
    • Single-threaded processes, one per request
    • Very fast
    • Consumes a lot of RAM
    • The only viable solution in some cases (e.g., PHP module is not thread-safe)
  • Worker:
    • A controller process that spawns other processes
    • Each child process can handle multiple threads — one thread per request
    • Issue: only one controller process...
  • Event:
    • Similar to the Worker model but optimized for keep-alive connections
    • Dedicated threads handle idle keep-alive requests
    • Default since Apache 2.4

nginx

  • Created in 2004
  • Goal: to solve the C10K problem
  • Asynchronous, event-driven architecture:
    • Worker processes (typically one per CPU core)
    • Each worker manages N sockets
    • Each socket can be in Listen (waiting for a connection) or Connection (connected to a client) state
    • Events occur on sockets and are handled by the worker:
      • If Listen socket → new connection → becomes Connection socket
      • If Connection socket → client sent a request → process it, then handle subsequent events
    • If the client sends another request on the same connection:
      • It’s treated as a new event
      • The worker doesn’t need to wait for that client to finish all its requests

Static and Dynamic Content

Apache

  • Static content: file-based
  • Dynamic content:
    • Additional modules, easily enabled (server process restart)
    • Each worker embeds the required language processor
    • Fully self-configured

nginx

  • Static content: excellent performance
  • Dynamic content:
    • Not handled directly
    • Forwarded to an external process; nginx waits for the response and relays it
    • Interpreter not always needed → lower overhead

Configuration

Apache

  • Centralized (text file)
  • Distributed (.htaccess)
    • For each request, Apache checks the entire path for .htaccess files and applies their directives
    • Advantages:
      • Configuration can be changed without restarting the server
      • Some users can configure their own part of the server
    • Disadvantage: performance impact

nginx

  • Centralized:
    • Much more efficient
    • More secure

Configuration

Apache

  • Originally designed as a web server → requests map directly to the file system
  • Takes the document root, appends the request, and looks it up in the file system
  • Other mappings possible (e.g., Alias, Location)

nginx

  • Acts as both a web server and a proxy
  • Translates to the file system only when needed
  • Accesses the file system only when ready to serve the response

Modules

Apache

  • Can be enabled/disabled dynamically
  • Apache core always present
  • Various functions:
    • Scripting (PHP, CGI, etc.)
    • URL rewriting
    • Authentication
    • Caching
    • Compression
    • Proxy
    • ...

nginx

  • Modules must be compiled into the core
  • Package management from software distributors cannot be used

DevOps

(in a nutshell)

A set of practices that combine software development (Dev) and IT operations management (Ops)

Software Development

  • Software must be placed in a context:
    • Runs on a specific operating system
    • Works with certain libraries
    • May require a specific framework
  • Must coexist with other software
  • Problem: incompatibility

Containers

  • Containers allow software to be moved from one system to another
  • Technology is relatively old, but became popular around 2013
  • Helps developers build applications quickly
  • Creates a dedicated, easily portable environment

Containers

  • Self-contained execution environment including all necessary components
  • Package containing:
    • software
    • all dependencies
    • libraries
    • other executables
    • configuration
  • Standard formats: App Container Image (ACI) or Open Container Initiative (OCI)

Containers vs Virtual Machines

  • VM: contains both the software and the operating system
  • VM: requires a server (hypervisor) running on a host OS
  • Container: only one operating system
  • Container: each container has its own mount point, but shares system resources

Types of Containers

  • Docker: software that simplifies the creation and management of containers
  • Podman: similar to Docker, developed by Red Hat, fully compatible with Docker

Running Containers

To run a container, you need two things: an image and a Container Runtime

A Container Runtime is software that runs and manages the components of a container

runC is a widely used runtime (others include gVisor and Kata)

The container runs as a process

Running Containers

The container runs as a process

  • Uses the host kernel services
  • Isolation and security requirements are managed by the kernel:
    • Control Groups
    • Namespaces

Control Groups

  • Used by the kernel to manage resource usage by processes
  • Organized hierarchically:
    • Managed as a virtual filesystem (/sys/)
  • Used to limit the resources available to a container

Control Groups

Limit the memory available to the process with PID 1102 to 50MB (52428800 bytes)

$ mkdir /sys/fs/cgroup/memory/group
$ echo 52428800 > /sys/fs/cgroup/memory/group/memory.limit_in_bytes
$ echo 1102 > /sys/fs/cgroup/memory/group/cgroup.procs

Namespaces

  • Used by the kernel to isolate processes
  • If a process is placed in a namespace, it can access only the resources within that namespace
  • Each container has its own set of namespaces

Image

Containers are based on images

  • An image is a description of a container
  • Docker uses an image to run a container
  • There can be multiple versions of the same image: a repository
  • Each version is identified by a tag:
    • latest: default tag for the most recent version

Union Filesystem

  • Images are stacked in a pile of layers:
    • Each layer is itself an image
    • Layers do not have associated tags
  • Layers are immutable
  • Multiple images can share the same layer
  • The top layer of the stack is the container layer and is writable

Container Management

  • docker ps: list running containers
  • docker ps -a: list all containers, including inactive ones
  • docker run --name con_name: run a container with name con_name
  • docker run -d con_name: run in detached (background) mode
  • docker run -it con_name: run in interactive mode
  • docker rm id: remove the container with a specific id
  • docker start id: start a stopped container with id
  • docker attach id: attach to a running container with id
  • docker stop id: stop the container with id

Filesystem

The filesystem of each container is completely isolated

  • Cannot access the filesystem of other containers or the host
  • Data volume: bridge between container FS and host FS
  • Maps a local filesystem to one inside the container

docker run -v /home/andrea:/home/container con_name

Networking

The network of each container is completely isolated

  • You can map a port between the container and the host
  • Warning: on Windows it runs as a VM, so the IP changes!

docker run -p 8088:80 con_name

Docker Configuration

  • The image must be described through a file:
    • Dockerfile
    • docker-compose
  • Defines the container that will then be executed

Dockerfile

Script that contains the operations to initialize the container

FROM ubuntu 
RUN apt update 
RUN apt install –y apache2 
RUN apt install –y apache2-utils 
RUN apt clean 
EXPOSE 80
CMD [“apache2ctl”, “-D”, “FOREGROUND”]

Dockerfile

  • FROM: base image to start from
  • ENV key=value: sets environment variables
  • RUN: executes commands inside the image (creates a new layer)
  • ADD: adds a file (including remote files) to the image
  • COPY: like ADD, but only for local files and faster
  • ENTRYPOINT: executes an instruction when the container starts; does not create a new layer
  • WORKDIR: container’s working directory
  • EXPOSE: ports on which the container will listen (not opened by default)
  • VOLUME: path in the container where a volume can be mounted (to be set at runtime)

Build

To create an image from a Dockerfile, you need to build it

  • docker build -t TAG build_context
  • The build context defines the path where the Dockerfile is located and where COPY/ADD commands operate from

Example

Dockerfile:

FROM httpd:2.4
EXPOSE 80
COPY ./src/ /usr/local/apache2/htdocs/

docker build -t our_server:1.0 .

docker run -d -P our_server:1.0

Docker-compose

Configuration tool that allows you to compose a container

version: '3.9'
services:
  apache:
    image: httpd:latest
    container_name: my-apache-app
    ports:
    - '8080:80'
    volumes:
    - ./website:/usr/local/apache2/htdocs

Server-side Programming

Web Server

Web Server

Program that delivers web documents upon request

Simple case:

  1. the user types the document URL (http://www.units.it/exam-results.html)
  2. browser→web server: “dear web server, please give me the document ‘exam-results.html’” (GET /exam-results.html HTTP/1.1)
  3. the web server looks for the document on disk
  4. web server→browser: “here is the HTML document”

someone had previously placed the document on disk

Web Server

(Example of) normal case:

  1. the user wants to buy item X
  2. browser→web server: complex request (contains some reference to X)
  3. the web server runs a program
    1. is X in stock?
    2. calculate the price of X for the user
    3. ...
    4. “creates” an HTML document with the result description
  4. web server→browser: “here is the HTML document”

Web Server: Another Point of View

The web server is a program that receives requests according to the HTTP protocol.

When it receives a request, it performs some operations — some of them to produce the HTML document:

  • find the document on disk
  • generate the document
  • generate the document and interact with other programs/computers
  • ...

Program to Generate the Document

What should the program do when “generating the document”? It depends:

  • “buy X” → document “you bought X
  • “register for exam E” → document “registration completed”
  • “what is the value of stock a” → document “stock information for a
  • ...

Do we need to rewrite a web server for every situation? No!

Server-side scripting/programming

Web Server-Side Scripting/Programming

  • The web server is modular/programmable
  • The programmer:
    • provides it with modules (programs)
    • tells it “for requests of type X, use module Y
  • The module programs:
    • execute within a context
    • must use/implement a specific interface
  • The modular/programmable server does the rest:
    • manages the connections
    • sets up the context
    • optionally “wakes up/puts to sleep” the modules
    • multithreading, sessions, ...

Modular/Programmable Web Server: Options

There are many:

  • PHP
  • ASP
  • Java
  • ...

We will look at a solution based on Node.js

Node.js

Node.js

  • Open-source and free server environment
  • Cross-platform (Windows, Linux, Unix, Mac OS X, ...)
  • Uses JavaScript on the server side
  • Based on asynchronous programming

Dynamic Web Documents

Reading a File Given an Input

Request handled by a traditional language (PHP, Java, ASP, ...):

  1. Receives the request and extracts the input parameter
  2. Sends the task to the file system
  3. Waits for the file system to open and read the file
  4. Sends the response to the client
  5. Ready to handle the next request

Dynamic Web Documents

Reading a File Given an Input

Request handled by Node.js:

  1. Receives the request and extracts the input parameter
  2. Sends the task to the file system
  3. Ready to handle the next request
  4. When the file system has read the file, it sends the response to the client

Node.js is Asynchronous

A single non-blocking thread is executed, and programming is done asynchronously.

Node.js: Capabilities

  • Generation of dynamic web documents
  • Server-side file system management
  • CRUD operations on databases
  • Form data collection

How It Works

  • Create a JavaScript file
  • Initialize it from the command line using the node executable
$ node myfile.js
  • When is it executed?
  • By default, immediately, but we are interested in when it receives an HTTP request

Modules

  • Modules are JavaScript libraries: collections of functions to be imported
  • Node.js includes some built-in modules by default
  • A module is included using require()
const http = require('http');

Modules

Modules can be created and included as desired

mymodule.js

exports.myFunction = function () {
  return "something";
};
const myf = require('./mymodule');
console.log(myf.myFunction());

Node.js as a Web Server

Main built-in module: http

const http = require('http');

http.createServer(function (req, res) {
  res.write('Good morning!');
  res.end();
}).listen(8080);

http Module

It provides various methods; the one we’re interested in is createServer():

  • Optional parameter requestListener:
    • invoked every time an HTTP request is received
    • handles the request and allows writing an HTTP response
    • parameters:
      • request: an IncomingMessage object
      • response: a ServerResponse object
  • Returns an HTTPServer object
    • which can listen on a port

Header Response

HTTP Response writing

const http = require('http');

http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/html'});
  res.write('Good morning!');
  res.end();
}).listen(8080);

Reading the Request

I can read the HTTP Request

const http = require('http');

http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/html'});
  res.write(req.url);
  res.end();
}).listen(8080);

Reading Parameters

I can parse the parameters from the query string

const http = require('http');
const url = require('url');

http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/html'});
  const q = url.parse(req.url, true).query;
  res.write(`${q.name} ${q.surname}`);
  res.end();
}).listen(8080);

File System Management

Let's read a document from disk:

  • We use the fs module
  • By default it's asynchronous, but a synchronous version exists
const http = require('http');
const fs = require('fs');

http.createServer(function (req, res) {
  fs.readFile('index.html', function(err, data) {
    res.writeHead(200, {'Content-Type': 'text/html'});
    res.write(data);
    return res.end();
  });
}).listen(8080);

File System Management

fs provides several functionalities:

  • File creation/update
    • fs.open()
    • fs.appendFile()
    • fs.writeFile()
  • File deletion
    • fs.unlink()
  • File renaming
    • fs.rename()

File System Management

const http = require('http');
const fs = require('fs');

http.createServer( (req, res) => {
  fs.readFile('index.html', (err, data) => {
    res.writeHead(200, {'Content-Type': 'text/html'});
    res.write(data);
    return res.end();
  });
}).listen(8080);

we can use arrow functions, promises, async, ...

Events

  • Every action in Node.js is an event
    • file opening
    • connection
    • ...
  • We can emit or listen to custom events using the events module
const http = require('http');
const events = require('events');
const eventEmitter = new events.EventEmitter();
const myEventHandler = function () {
  console.log('I heard something!');
}
eventEmitter.on('noise', myEventHandler);
eventEmitter.emit('noise');

Example: upload form (1)

const http = require('http');

http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/html'});
  res.write('
'); res.write('
'); res.write(''); res.write('
'); return res.end(); }).listen(8080);

Example: upload form (2)

const http = require('http');
const formidable = require('formidable');

http.createServer(function (req, res) {
  if (req.url == '/fileupload') {
    const form = new formidable.IncomingForm();
    form.parse(req, function (err, fields, files) {
      res.write('File uploaded');
      res.end();
    });
  } else {
    res.writeHead(200, {'Content-Type': 'text/html'});
    res.write('
'); res.write('
'); res.write(''); res.write('
'); return res.end(); } }).listen(8080);

Example: upload form (3)

const fs = require('fs');
/* ... */

http.createServer(function (req, res) {
  if (req.url == '/fileupload') {
    const form = new formidable.IncomingForm();
    form.parse(req, function (err, fields, files) {
      const oldpath = files.filetoupload.filepath;
      const newpath = `${__dirname}/${files.filetoupload.originalFilename}`;
      fs.copyFile(oldpath, newpath, function (err) {
        if (err) throw err;
        res.write('File uploaded and moved!');
        res.end();
      });
    });
  } else {
    res.writeHead(200, {'Content-Type': 'text/html'});
    res.write('...');
    return res.end();
  }
}).listen(8080);

HTML Templates

Creating a web document from scratch is inconvenient

  • I might want to reuse some parts
  • I want to avoid putting HTML directly into my JS code

Solution: templates

HTML Templates

HTML structure with variable parts:

  • I modify only the variable parts at runtime
  • I don’t include HTML inside my code
  • I can use a module that works as a template engine

Which module?

Node Exercise 1

Create (at least) 3 files (JSON, XML, or text) objects, each containing a record for an animal. Each record must include at least 3 attributes (for example: name, color, ...).

Create an HTML document with a text box. When the user types the name of an animal, the document updates to show a table with that animal’s data, if available.

Provide the response through a Node.js server.

Node Exercise 2

Write an HTML document with an input box and a button: when the user clicks the button, the page displays a list of the first 20 permutations of the word typed into the box.

The permutations are computed on the server using Node.js and sent back to the web page.

Limits of http

  • Handling requests to different URLs
  • Hard to manage different methods (GET, POST, DELETE, ...)
  • Serving static files
  • Using templates

Solution? Let’s use a framework!

Express

The most widely used framework in the Node.js ecosystem is Express

  • Handlers for managing different methods and URLs
  • Integrates template engines
  • Allows serving static resources
  • Easily extensible through a middleware pipeline

Express

  • By default, Express is very minimal
  • There are many modules to handle common use cases:
    • cookies
    • sessions
    • authentication
    • headers
    • security
    • ...
  • They are all based on the concept of middleware
  • Drawback: we must choose the right library

"Opinionated" vs. "Unopinionated"

Frameworks can be divided into two categories:

  • Opinionated
    • They define “one way” to solve a problem
    • Faster development within a specific domain
    • Less flexibility
  • Unopinionated
    • They don’t define “one way” to solve a problem
    • Give more freedom to the developer
    • More code to write

Express is unopinionated

Express

  • A web application typically:
    • Waits for an HTTP Request
    • Decides what action to take based on the requested URL and method
    • If necessary, generates dynamic HTML
    • Sends back the HTTP Response
  • Express allows you to specify:
    • Functions to be called depending on the requested method and URL
    • Which template engine to use
    • Where to find static resources and templates
    • Which middleware to use to handle everything else

Express: example

const express = require("express");
const app = express();
const port = 3000;

app.get("/", (req, res) => {
  res.send("Good morning!");
});

app.listen(port, () => {
  console.log(`Listening on port ${port}!`);
});

Routing

  • What action should be taken based on the requested URL and method?
  • A callback is defined for each relevant option
  • The callback is assigned using a method dedicated to each HTTP method:
    • get()
    • post()
    • delete()
    • put()
    • all()
  • The parameters are: the resource pattern and the callback

Routing: example (1)

const express = require("express");
const app = express();
const port = 3000;

app.get('/book', (req, res) => { res.send('Read book') });
app.post('/book', (req, res) => { res.send('Add book') });
app.put('/book', (req, res) => { res.send('Edit book') });

app.listen(port, () => {
console.log(`Listening on port ${port}!`);
});

Routing: example (2)

It can be compacted

const express = require("express");
const app = express();
const port = 3000;

app.route('/book')
  .get((req, res) => { res.send('Read book') })
  .post((req, res) => { res.send('Add book') })
  .put((req, res) => { res.send('Edit book') });

app.listen(port, () => {
  console.log(`Listening on port ${port}!`);
});

Response

  • res.end() ends the response
  • res.json() sends a JSON object
  • res.redirect() forces the client to perform a redirect
  • res.render() calls a template engine
  • res.send() sends a general-purpose response
  • ... and many others

Routing

It is often useful to group handlers for a section of the site

wiki.js

const express = require("express");
const router = express.Router();

router.get("/", function (req, res) {
  res.send("Wiki home page");
});

router.get("/about", function (req, res) {
  res.send("Information");
});

module.exports = router;

app.js

const wiki = require("./wiki.js");
/* … */
app.use("/wiki", wiki);

Routing paths

  • Routing paths can also be patterns
  • ?: the resource may have 0 or 1 repetition of the previous character/group
  • +: the resource may have 1 or more repetitions of the previous character/group
  • *: the resource can have an arbitrary string in place of the symbol
  • (): the string between parentheses is a group

Routing parameters

A part of the resource can be parametric: a named segment

A named segment is defined with the : prefix

app.get("/user/:userId/book/:bookId", (req, res) => {
  console.log(req.params.userId, req.params.bookId);
  res.send(req.params);
});

Middleware

  • Widely used in Express applications
    • Serve static files
    • Handle errors
    • Compress responses
    • ... and much more
  • They are a “stack” of functions to be executed
  • Route functions conclude the HTTP request-response cycle

Middleware

Middleware functions:

  • Can access:
    • the request object
    • the response object
    • the next middleware function
  • They can:
    • Execute code
    • Modify the request and response objects
    • End the request-response cycle
    • Call the next middleware in the stack with next()

Middleware

  • Middleware can perform any operation
  • They are defined using the use() method
  • They can end the request-response cycle
  • If not, they call the next middleware with next()

Middleware

const express = require("express");
const logger = require("morgan");
const app = express();
app.use(logger("dev"))

Middleware

Interface specification for the various methods get(), post(), delete(), ...

app.METHOD(path, callback [, callback ...])
  • path → The path for which the middleware function is invoked; can be any of:
    • A string representing a path
    • A path pattern
    • A regular expression pattern to match paths
    • An array of any of the above
  • callback → Callback functions; can be:
    • A single middleware function
    • A sequence of middleware functions (comma-separated)
    • An array of middleware functions
    • A combination of all of the above

Application-level middleware

Run a function for every request

app.use((req, res, next) => {
  /* do something */
  next();
})

Run a function for a specific resource

app.use('/user/:id', (req, res, next) => {
  /* do something */
  next();
});

Application-level middleware

Run a function when a GET request is made to a specific resource

app.get('/user/:id', (req, res, next) => {
  /* do something */
  next();
});

Run a sequence of functions

app.use('/user/:id', (req, res, next) => {
  /* do something */
  next();
}, (req, res, next) => {
  /* do something */
  next();
})

Static files

A built-in middleware to manage static content in Express is express.static

Useful when handling requests for images, CSS, JavaScript, and static pages. If the file isn’t found, the request is passed to the next middleware.

const express = require("express");
app.use(express.static("public"));
app.use(express.static("media"));
app.listen(port, function () {
 console.log('Static file server example');
});

Body parsing

The body of an HTTP request can contain different kinds of data

There is Express middleware to parse the request body

  • form with parameters → express.urlencoded()
  • json → express.json()
const express = require("express");
app.use(express.urlencoded());
app.post("/form", (req, res) => {
 console.log(req.body.param1)
});
app.listen(port, function () {
 console.log('Static file server example');
});

Sessions

HTTP: stateless

HTTP is a stateless communication protocol

Simple case:

  1. client C makes request req1 to web server S which replies with resp1
  2. client C makes request req2 to web server S which replies with resp2

The second request is independent of the first: resp2 is produced solely based on req2!

otherwise it’s called stateful

HTTP: stateless web applications?

Real-world need (web application):

  1. CS: req1, SC: resp1 = f(req1)
  2. CS: req2, SC: resp2 = f(req2, req1)

From another viewpoint:

  1. req1resp1 = f(req1, ∅), s1 = g(req1, ∅)
  2. req2resp2 = f(req2, s1), s2 = g(req2, s1)

Stateful web application

  1. req1resp1 = f(req1, ∅), s1 = g(req1, ∅)
  2. req2resp2 = f(req2, s1), s2 = g(req2, s1)
  • f and g are the web application (e.g., e-commerce)
  • req1: “I’m customer X, show me the dog beds page”
  • resp1: dog beds page with “hello customer X
  • s1: <customer=X;cart=∅>
  • req2: “buy dog bed Y
  • resp2: page “well done X, you bought bed Y
  • s2: <customer=X;cart=[Y]>

State

From another viewpoint:

  1. s := s0
  2. reqresp = f(req, s), s := g(req, s)

s is the state of the dialogue between C and S

  • it could contain many things (the whole history since the first request from C, app data, ...)
  • when it contains short-term data, it’s called a session

State: server with multiple clients

The web server S is multithreaded:

  • there can be multiple simultaneous dialogues with different clients C
  • when a request req arrives from Ci, how does S use the right state among the various si?

State: server with multiple clients

Wrong answer:

S knows who Ci is and “fetches” si from a list/map

  • What does S know about C when req arrives? (in other words: what does req contain about C?)
    • IP address
    • a very rough description of something related to some C (user-agent)
  • Not good because of:
    • NAT
    • anonymizers
    • ...

Server with multiple clients: basic idea

S, on the “first” request from C:

  • in the response: “in all subsequent requests, include this token t
  • saves t in a dedicated list

When a request req arrives from a C:

  • if it doesn’t include the token, it’s the “first” one
  • otherwise retrieve the state

Requires client cooperation!

  • it might not understand/discard the token
  • it might include a random token in req

The token could be S; usually it’s much “smaller”

Server with multiple clients: basic idea

S includes in the response:
“in all subsequent requests, include this token t

Mechanisms:

  • cookies: the value of an HTTP header
    • S puts t into cookie c in the response (t = c)
    • C includes c in requests
  • URL rewriting
    • S rewrites all internal links in response documents to C, appending t as a GET parameter value

      href="store/dogs/index.jsp?type=jack_russel&sess_id=t

Cookies vs. URL rewriting

  • C might not accept cookies
  • it’s unlikely that C will “clean” links from the sess_id
  • ... but the cookie solution tends to be more convenient/elegant

Sessions in Express

  • We use the express-session middleware
  • It is cookie-based
  • A session property is created on the req object
  • Managed at the application level: be cautious if tied to authentication!
  • Stored in memory (to persist it, you can connect it to a database)
  • secret: required parameter, the token used to sign the session ID cookie
  • resave: forces saving the session; not generally required, and the default value (true) is deprecated

Sessions in Express

const session = require('express-session');
app.use(session({
    secret: 'secret',
    resave: false
}));
app.post('/login', (req, res) => {
    /* code to verify if the user exists */
    if(user !== null) {
        req.session.user = {
              email: user.email,
              name: user.name
        };
        res.redirect('/account');
    } else {
       /* Invalid login */
    }
});
app.get('/info', (req, res) => {
    if(!req.session.user) {
        res.redirect('/login');
    } else {
        res.send(req.session.user);
    }
});

Authorization and Authentication

Basic need

Access to certain resources must be restricted

  • "access to resources" ≈ "performing operations"
  • "restricted"...
    • in time (from 9:00 to 19:00)
    • by physical origin (only requests coming from host/network C)
    • by type of channel (HTTPS)
    • ...
    • by the identity of the requester

Why restrict access? Security!

Access limitation and requester identity

Access to certain resources must be restricted based on the identity of the requester

  1. Client → Server: “I’d like to access resource req
  2. Server: “Is req a restricted resource? Yes”
  3. Server → Client: “Who are you?”
  4. Client → Server: “I’m C }authentication
  5. Server: “Is the client really C? Yes”
  6. Server: “Can C access req? Yes” ← authorization
  7. Server → Client: “Here’s req!”

At this point, the server considers C as logged in for a certain time or number of requests (~ sessions)

Authentication and authorization

  • S: “Who are you?” C: “I’m CS: “Is the client really C? Yes”

    • The server knows how to ask the client for its identity
    • It must also be able to verify the claim made by C: generally complicated...
  • S: “Can C access req? Yes”

    • The server knows who can access req: simple (a list)

Declarative vs. Programmatic security

For us, “security” ≈ “authentication/authorization”

Declarative → authentication/authorization processes are defined in the configuration

  • which resources are restricted
  • which credential request mechanism to use, and how to validate them (authentication)
  • for each resource, who can access it (authorization)

Declarative vs. Programmatic security

Programmatic → authentication/authorization processes are defined (also) in the code

  • Necessary for non-trivial cases

    resource req can be accessed by users U1, U2, U3 only if user U0 has accessed req at least 5 times

Defined manually by the programmer

Authentication in Express

It can be implemented in two ways

  • Custom solution
    • Using sessions
  • Using middleware
    • passport
    • Ready-made library, but quite powerful

Authentication in Express

Custom-built

app.post('/login', function(req, res){
   /* retrieve credentials from DB */
   if(user.id === req.body.id && user.pass === req.body.pass){
      req.session.user = user;
      res.redirect('/restricted');
   }
   res.send('Invalid credentials');
});
app.get('/restricted', checkSignIn, function(req, res){
   res.send('protected data');
});
function checkSignIn(req, res, next){
   if(req.session.user){ return next() }
   next(new Error("Not logged in!"));
}

Authentication in Express

Passport.js

const passport = require('passport');
const LocalStrategy = require('passport-local');
passport.use(new LocalStrategy((user, pass, done) => {
  /* check if username and password are in the DB */
  if(!authenticated){ return done(null, false); }
  if(authenticated) return done(user);
});

app.get("/restricted", (req, res, next) => { 
    /* handle login */
    if (req.isAuthenticated()) { return next(); }
    res.redirect('/')
  },
  (req, res) => {
    /* method body if authenticated */
});

JWT - JSON Web Token

JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.
  • Information is no longer stored in the session, but on the client.
  • How? With a signed string (token)!
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ. SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Three sections, separated by “.” and Base64 encoded

  • Header → type of token and algorithm used for signing
  • Payload
  • Signature

JWT - JSON Web Token

  1. The client sends credentials to the server
  2. If valid, the server signs and returns the JWT
  3. In subsequent communications, the client sends the JWT to the server
  4. The server verifies the signature and extracts the data

How is the token sent to the server?

  • HTTP Header: Authorization: Bearer token
  • Custom...

JWT - JSON Web Token

  1. The client sends credentials to the server
  2. If valid, the server signs and returns the JWT
  3. In subsequent communications, the client sends the JWT to the server
  4. The server verifies the signature and extracts the data

What are the benefits?

  • The servers in steps 1 and 3 can be different
  • The same credentials can be used across multiple servers
  • No need to manually handle sessions (specific to each container)

JWT in Node.js

const jwt = require('jsonwebtoken');
app.post('/api/login', (req,res)=>{
    const user = { /* user data */ };
    jwt.sign({user:user},'secretkey',(err,token)=>{
        res.json({token,});
    });
});
app.post('/api/profile', (req,res,next) => {
    const bearerHeader = req.headers['authorization'];
    if(typeof bearerHeader!=='undefined'){
        const bearerToken = bearerHeader.split(' ')[1];
        req.token=bearerToken;
        next();
    } else {
        res.sendStatus(403);
    }, (req,res)=>{
    jwt.verify(req.token, 'secretkey', (err, authData)=>{  
        if(err){ res.sendStatus(403);}
        else{ res.json({ /* data */ });}
    });
});

JWT in Node.js

const jwt = require('jsonwebtoken');
app.post('/api/login', (req,res)=>{
    const user = { /* user data */ };
    const token = jwt.sign({user:user},'secretkey',{expiresIn: 86400});
    res.cookie("token", token, {httpOnly: true});
    res.json("Authenticated!");
});
app.post('/api/profile', (req,res,next) => {
    const bearerHeader = req.headers['authorization'];
    if(typeof bearerHeader!=='undefined'){
        const bearerToken = bearerHeader.split(' ')[1];
        req.token=bearerToken;
        next();
    } else {
        res.sendStatus(403);
    }, (req,res)=>{
    jwt.verify(req.token, 'secretkey', (err, authData)=>{  
        if(err){ res.sendStatus(403);}
        else{ res.json({ /* data */ });}
    });
});

NPM

Node Package Manager

  • Included in Node.js
  • Not limited to Node.js usage
  • Manages the installation of modules/packages (synonyms)
  • Makes developers’ life easier...

package.json

  • Application manifest
  • Lists the name and version of required modules (dependencies)
  • Defines version constraints (e.g., can it be updated?)
  • Allows the creation of NPM scripts

It can be created easily with npm init

Installing, removing, and updating

  • Add modules: npm install something --save

    Why --save?

    • Modules are downloaded into the node_modules folder
    • We don’t want to include that folder in version control → we save dependencies in package.json
  • Development-only dependencies: npm install something --save-dev
  • Install required modules: npm install
    • In production: npm install --production
  • Remove a package: npm uninstall something --save
  • Update a package: npm update something
  • List installed packages: npm list
  • something can specify a version using @

Versions

Versions always follow the Major.Minor.Patch format

  • Major: may break the API
  • Minor: adds new features without breaking the API
  • Patch: fixes bugs

^Maj.min.patch → installs the latest minor/patch version

~Maj.min.patch → installs the latest patch version

Maj.min.patch → installs exactly that version

* → installs the most recent version (dangerous)

Local and global packages

By default, packages are local, specific to a single project.

Global packages are installed system-wide.

  • npm install -g something

    May require sudo

  • npm remove -g something

NPM Scripts

Allow you to run custom tasks

  • Defined in package.json
  • Executed with npm run scriptName
  • Some platforms look for a start script

    It can be executed directly with npm start, without run

Web Services

Web App Architecture

As seen in the course:

User

Browser

Modular Web Server
(Node.js + Express)

DBMS

User and App

The user can use the app through:

  • desktop browser
  • smartphone browser
  • smartphone app
  • smart TV app
  • ...
  • the user is another app

Everyone wants to talk to us through the Internet...

Interoperability

Web Services

Web services provide a standard means of interoperating between different software applications, running on a variety of platforms and/or frameworks.

But what changes compared to a regular web page?

Interoperability

Web Services

Web services provide a standard means of interoperating between different software applications, running on a variety of platforms and/or frameworks.

But what changes compared to a regular web page?

The recipient changes:

  • Web Page → human being
  • Web Service → program

Interoperability

Web Services

Web services provide a standard means of interoperating between different software applications, running on a variety of platforms and/or frameworks.

There are three possible paths:

  1. Self-built
  2. Follow an existing standard
  3. Implement a predefined design pattern

Which one to choose?

  • Who needs to use the system?
  • Which programming languages must it support?

Path 1: Self-built

Self-Built Solution

We define the standard used to expose the service

  • We already have all the tools to do it
  • It’s essential to provide a specification for input and output
const express = require('express');
const app = express();
app.get('*', (req, res) => {
  if(req.query.program !== undefined){
    /*create XML response for the calling program*/
  } else {
    /*create HTML page for the human user*/
  }
});

Self-Built Solution

We define the standard used to expose the service.

Problems:

  • Manual deserialization of input (strings)
  • Which programming languages will we support?
  • Need to describe everything obsessively
    • “Numbers will use the period as a decimal separator”
    • “The boolean false value is 'FALSE'; anything else is true”
    • “An integer can be at most 64 bits”
    • ...
  • Not tragic if producer == consumer
  • ...but what happens if others need to use it tomorrow?

Path 2: Follow a Standard

Following a Standard: A Brief History

  • 1990: TCP/IP becomes THE standard
  • Many technologies are born, independent of programming language:
    • CORBA: uses an Interface Description Language to describe the exposed interfaces, and CORBA handles mapping them to the implementation language.

      And what about C, which isn’t object-oriented?

    • DCOM (Distributed COM): Microsoft’s response to CORBA. Adds marshalling and distributed garbage collection to COM.

      Firewalls aren’t happy—doesn’t use port 80

    • Java RMI (Remote Method Invocation): calls from one JVM to another, later extended to expose CORBA.

Following a Standard: A Brief History

  • 2000: the religion of 🕯 XML 🕯 is born
  • XML-RPC (Remote Procedure Call):
    • uses XML to encode calls;
    • transport via HTTP;
    • parameters have no names and must be passed in order;
    • 6 pages of specifications.
  • SOAP (Simple Object Access Protocol): evolved XML-RPC
    • uses XML to encode calls;
    • uses HTTP(s), SMTP, JMS, ...;
    • named parameters;
    • designed to also transmit documents;
    • 44 pages of specifications.

XML-RPC was created because Microsoft hesitated to approve SOAP!

SOAP

A W3C standard, currently at version 1.2. Main elements:

Envelope

Header
Body
Fault

Header: meta-information (e.g., version, transaction info, etc.)

Only Envelope and Body are mandatory

SOAP Message

<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope/" soap:encodingStyle="http://www.w3.org/2003/05/soap-encoding">
  <soap:Header>
    ...
  </soap:Header>
  <soap:Body>
    ...
    <soap:Fault>
      ...
    </soap:Fault>
  </soap:Body>
</soap:Envelope>

The data encoding is not predefined, and multiple encoding types can coexist

SOAP Body

Used for Requests...

<soap:Body>
  <m:GetPrice xmlns:m="http://www.w3c.com/prices">
    <m:Item>Apples</m:Item>
  </m:GetPrice>
</soap:Body>

...and Response

<soap:Body>
  <m:GetPriceResponse xmlns:m="http://www.w3c.com/prices">
    <m:Price>1.90</m:Price>
  </m:GetPriceResponse>
</soap:Body>

...and possible errors

SOAP Binding

So far, we haven’t talked about the channel or the server we communicate with...

If HTTP is used, the headers must specify:

  • Content-Type: usually application/soap+xml
  • Content-Length
  • SOAPAction: "URI"
    • does not necessarily have to be resolvable;
    • does not depend on the SOAP specifications, but on the application

SOAP: complete message

POST /InStock HTTP/1.1
Host: www.example.org
Content-Type: application/soap+xml; charset=utf-8
Content-Length: nnn
SOAPAction: "/GetStockPrice"

<?xml version="1.0"?>
  <soap:Envelope
  xmlns:soap="http://www.w3.org/2003/05/soap-envelope/"
  soap:encodingStyle="http://www.w3.org/2003/05/soap-encoding">
  <soap:Body xmlns:m="http://www.example.org/stock">
    <m:GetStockPrice>
      <m:StockName>IBM</m:StockName>
    </m:GetStockPrice>
  </soap:Body>

</soap:Envelope>

SOAP Errors

The server in response should only return:

  • 2xx: message received and understood
    • there might still be errors in Body/Fault
  • 500: the message cannot be processed
    • missing information
    • not understood, etc.
    • should still return an envelope whose Body/Fault contains the explanation.

SOAP and Attachments

And what if we need to send attachments?

Solution 1: encoded in the envelope using BASE64

...very inefficient...

SOAP and Attachments - MTOM

And what if we need to send attachments?

Solution 2: Message Transmission Optimization Mechanism

using MIME and Multipart

MIME-version: 1.0
Content-Type: Multipart/Related; ...
--MIME_boundary
Content-Type: text/xml; ...
<?xml version="1.0" ?>
<env:Envelope ...
  <someTag href="cid:attached.gif@company.com"/>
</end:Envelope>
...
--MIME_boundary
Content-Type: image/gif
Content-Transfer-Encoding: binary
Content-ID: <"attached.gif@company.com">
... image's binary...

SOAP and Node.js

How do I build a Web Service?

  1. Write a program and handle the POST method
    • a lot of work
    • isn’t there already a ready-made solution?

SOAP and Node.js

How do I build a Web Service?

  1. Write my own script and handle the POST method
    • a lot of work
    • isn’t there already a ready-made solution?
  2. Use node-soap:
    • Dedicated module for SOAP services
    • Alternative to Express

SOAP and Documentation

But I still have a big problem: how can the user know

  • which Web Services I expose?
  • what parameters they accept?
  • what I will get as a response?

Do I have to write documentation?

SOAP and Documentation

But I still have a big problem: how can the user know

  • which Web Services I expose?
  • what parameters they accept?
  • what I will get as a response?

Do I have to write documentation? NO!

Web Services Description Language, W3C standard

WSDL

Uses XML to define interfaces, composed of four elements:

  • <types>: data types used by the WS (not necessary if using already known primitives)
  • <message>: definition of the data being transmitted
  • <portType>: operations that can be performed and related messages
  • <binding>: protocol and data format used for each port

WSDL

<portType> doesn’t handle only request/response:

  • One-way: the WS receives data but doesn’t return any
  • Request-response: the WS receives and sends data
  • Solicit-response: the WS sends data to the client and waits for a response
  • Notification: the WS only sends data

You switch between them by changing the order and presence of input/output elements

WSDL - Example

<message name="getTermRequest">
  <part name="term" type="xs:string"/>
</message>
<message name="getTermResponse">
  <part name="value" type="xs:string"/>
</message>

<portType name="glossaryTerms">
  <operation name="getTerm">
    <input message="getTermRequest"/>
    <output message="getTermResponse"/>
  </operation>
</portType>

<binding type="glossaryTerms" name="b1">
   <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
   <operation>
     <soap:operation soapAction="http://example.com/getTerm"/>
     <input><soap:body use="literal"/></input>
     <output><soap:body use="literal"/></output>
  </operation>
</binding>

Path 3: Implement a Design Pattern

RESTful Web Service

Representational State Transfer (RESTful)

  • transfer of the (current or desired) state of a resource representation
  • operations on resources are the typical ones (CRUD: create, read, update, delete)
  • not a standard for describing the interface
  • not a standard for describing data exchange
  • no strict client-server contract
  • a REST client is comparable to a browser

Originates from Roy T. Fielding’s dissertation

RESTful Web Service

Key elements:

  • A REST API should be independent of any single communication protocol, though its successful mapping to a given protocol may depend on the availability of metadata, choice of methods, etc.
  • A REST API should not introduce any changes to communication protocols apart from filling out or fixing the underspecified parts of standard protocols.

RESTful Web Service: HATEOAS

Hypermedia as the Engine of Application State

  • HTTP + JSON
  • This is the most common way to implement REST APIs
  • A base URL for each resource, e.g. http://myapp.com/api/entry
  • The Java technology is JAX-RS
    • no true standard exists
    • does not generate documentation for clients (but tools can help: Swagger, compliant with OpenAPI)

RESTful WS: HATEOAS Operations

  • Operations on a collection: http://myapp.com/api/entry
    • GET: reads the items in the collection (optionally with parameters)
    • PUT: replaces the collection
    • POST: inserts an element into the collection
    • PATCH: partial update (?)
    • DELETE: removes the entire collection
  • Operations on a single item: http://myapp.com/api/entry/17
    • GET: reads item 17
    • PUT: replaces item 17
    • DELETE: removes item 17
    • ...

it’s not necessary to implement all of them

REST: Example

Resource Method
Book list [GET] /books
Book details [GET] /books/<id>
Create a book [POST] /books
Edit a book (or create a book with a specific ID) [PUT] /books/<id>
Delete a book [DELETE] /books/<id>

RESTful WS: example

GET http://myapp.com/api/entry

[{
    id: 17,
    date: "2013/15/5 11:58:00",
    amount: 17.38,
    currency: "eur",
    description: "pranzo"
  }, {
    id: 185,
    date: "2013/15/5 8:30:00",
    amount: 1.20,
    currency: "eur",
    description: "caffè"
  }]

RESTful: OpenAPI

Some REST ideas are great, but in practice unworkable... documentation is needed!

OpenAPI is an API description format for REST APIs
  • Originally called the "Swagger Specification"
  • A set of tools for generating code and documentation
    • server code from specifications
    • documentation from server code
    • clients from documentation
  • Uses YAML or JSON

RESTful: How to Create Them

Some options:

  • by hand
  • Express!

Vue.js

Vue.js

Vue (pronounced /vjuː/, like view) is a progressive framework for building user interfaces. Unlike other monolithic frameworks, Vue is designed from the ground up to be incrementally adoptable.
  • It is a JavaScript framework
  • It simplifies the creation of GUIs and front-end interfaces
  • Progressive: you don’t need to learn everything at once

Why Vue.js

  • Relatively less steep learning curve compared to other frameworks (REACT, Angular, ...)
  • Very lightweight (20KB)
  • Components:
    • clean and organized project structure
    • we don’t separate responsibilities (MVC), but components (HTML/style/code together)

Vue.js: usage

I need to include Vue in my web document

It’s convenient to use a CDN:

<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>

Production version (without warnings and debug):

<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>

Vue.js: usage

Every application starts by creating a new Vue instance through createApp():

const { createApp } = Vue
const app = createApp({
  /* options */
})

Vue.js: mounting

An application must be attached to a container, an HTML element where the application is rendered

This is done using the mount() method:

  • it is called after configuring and initializing the app
  • it takes as input an HTML element or a CSS selector
app.mount('#app')

Reactivity system

Vue.js is based on the reactivity system: if a JavaScript object is modified, the view gets updated

Data

Objects that I want to control with the reactivity system must be passed through the data property

data will be a method that returns the objects to monitor.

The reactivity system will "react" every time one of these properties changes by performing a re-render.

var data = { a: 1 }

const app = createApp({
  data() { return data }
})

Interpolations

Vue.js uses a syntax based on dynamic HTML templates. To bind data to the render, it provides interpolation features

  • {{ x }}, called "mustache", is replaced in the HTML with the evaluation of x
  • if I want to specify that x must be rendered as HTML, I must use the v-html directive

Methods, functions, and behaviors

  • You can associate functions to a Vue instance
  • These must be placed in the methods property
  • These functions are also reactive to changes
  • They can be used as DOM event handlers

Directives

  • Directives are special attributes with the v- prefix
  • They are meant to receive a single JavaScript expression
  • Directives apply a reactive effect when their expression changes
  • They can accept arguments passed with :

Now you see me

The v-if directive removes/inserts the element depending on whether the "seen" expression is false/true

Directives

  • v-if shows or hides an element if the expression is true or false
  • v-for repeats the component for each element of an iterable object
  • v-on:event associates a function to the event event
  • v-bind:attr binds the value of an attribute attr to an expression
  • v-html sets the element’s innerHTML with the expression

Shortcuts

  • Some directives can be shortened to improve code readability
  • v-on:event@event
  • v-bind:attr:attr

Computed Properties

  • Special properties with dynamic values
  • Derived from other properties
  • Defined inside the computed property
  • They update automatically when a dependency changes
  • They allow caching and prevent calling functions unnecessarily
const { createApp } = Vue
const data = {firstname: "Andrea", lastname: "De Lorenzo"};
const app = createApp({
    data() {
        return data
    },
    computed: {
        fullname: function() {
          return this.firstname + ' ' + this.lastname;
        }
      }
  });
app.mount('#app');

CSS Classes

  • We can modify the class attribute using the :class directive
  • Very convenient for manipulating how the DOM appears
  • We can associate booleans to each class: :class="{ 'cl1': hasCl1, 'cl2': hasCl2}"
  • We can also do it as an array: :class="['cl1','cl2']"

Events

  • With v-on:event or @event we can handle events
  • We can add modifiers:
    • .stop: stops bubbling
    • .prevent: prevents the default action
    • .once: calls the callback only once, then removes it
<a href="..." @click.prevent="onClick">Link</a>

User Input

  • You can bind the user's input to a bidirectional model:
    • Changes to the input or the model will affect the other component
  • The model is created with the v-model directive
<main id="app">
    
    {{text}}
</main>
const app = createApp({
    data() {
      return { text: "" }
    }
});

Components

  • They are an enriched portion of HTML
  • You can use them with a custom tag <my-comp></my-comp>
  • If defined natively (without a build step), they must be declared with some caveats
  • They must be registered before creating the Vue instance
    • Globally if available throughout the whole app
    • Locally if only inside another component

Components

Global registration

app.component('mio-comp', {
  [...] 
});

Local registration

export default {
  [...],
  components: {
    'mio-comp': {
      [...] 
    }
  }
});

Components: data

  • A component can be given a data property
  • data represents the reactive data model for that component
  • You don’t pass an object, but a function!
    • You may have multiple instances of the same component
    • You want to have separate data models for each component
export default {
  data: function() {
    return {
      name: 'Andrea',
      age: 37
    };
  }
}

Components: template

  • Each component will have an HTML structure
  • It is provided through the template parameter
  • It can be defined in different ways:
    • String
    • Single File Components

Components

Inline string

const ButtonCounter = {
  data() {
    return {
      count: 0
    }
  },
  template: `
    `
}

Components

String in a separate module

export default {
  data() {
    return {
      count: 0
    }
  },
  template: `
    `
}

Components: props

  • Each component has an isolated scope
  • You can pass values to the component from another component
  • These values are defined through the props property
    • Array of strings
    • Object properties (you can define the type)
  • They can be static or dynamic
    • Static: component attributes
    • Dynamic: shortcut using the name of the prop

Components: props

<div id="app">
  <people-list :people="people"></people-list>
  <div>
    <input v-model="name" placeholder="name" /><br />
    <input v-model="surname" placeholder="surname" /><br />
    <button @click.prevent="addPerson">Add person</button>
  </div>
</div>

Components: props

const { createApp } = Vue

const PeopleList = {
    props: ['people'],
    template: ``
}
const Person = {
    props: ['person'],
    template: `
{{ person.name }} {{ person.surname }}
` } const app = createApp({ data() { return { people: [{ name: 'Andrea', surname: 'De Lorenzo' }], name: '', surname: ''}}, methods: { addPerson: function() { this.people.push({ name: this.name, surname: this.surname }); this.name = ''; this.surname = ''; } } }); app.component("Person", Person); app.component("PeopleList", PeopleList); app.mount('#app');

Components: single file component

  • You can define components in separate files that contain everything
  • Very convenient and organized:
    • Each component will be a source file
    • Each component contains style, functionality, and HTML structure
  • Requires a build tool:

Components: single file component

  • Each component will be a source file
  • Each component contains style, functionality, and HTML structure

Output

Functionality

Stile

Creating a component

  • Create a .vue file
  • Create the three sections:
    • <template>
    • <script>
    • <style>
  • Import the file into the component where it will be used

Routing

Web apps often rely on the concept of a Single Page Application

The entire application lives inside a single HTML page whose components change dynamically depending on the content

Routing

It’s useful to offer permalinks to resources in a Single Page Application

This is done by using URL anchors (the part after #)

In Vue.js, routing is used to load templates based on the URL

Routing

import Home from './Home.js'
import About from './About.js'
import NotFound from './NotFound.js'

const routes = {
  '/': Home,
  '/about': About
}
export default {
  data() {
    return { currentPath: window.location.hash }
  },
  computed: {
    currentView() {
      return routes[this.currentPath.slice(1) || '/'] || NotFound
    }
  },
  mounted() {
    window.addEventListener('hashchange', () => {
      this.currentPath = window.location.hash
    })
  },
  template: `<a href="#/">Home</a> |<a href="#/about">About</a> | <a href="#/non-existent-path">Broken Link</a>
  <current-view><</current-view>`
}

Lifecycle Hooks

Every Vue component goes through a life cycle, from creation to destruction

Lifecycle Hooks allow you to run code at specific moments of this cycle

Lifecycle phases

  • Creation – the component is instantiated
  • Mounting – the template is rendered and mounted into the DOM
  • Updating – data changes and the view updates
  • Unmouting – the component is removed and cleaned up

Main hooks

  • created(): initial data available
  • mounted(): component is in the DOM
  • updated(): the view has been updated
  • unmounted(): cleanup before removal

created()

Executed after the instance is created but before mounting

  • Props available
  • Initial data available
  • DOM is not accessible yet
created() {
  console.log("Component created");
}

mounted()

Executed when the component is mounted into the DOM

  • You can access the DOM
  • Ideal for fetch calls, external libraries, charts
mounted() {
  console.log("DOM ready!");
  console.log(this.$el); // DOM node reference
}

updated()

Executed every time the view updates as a result of reactive data changes

  • Avoid heavy tasks (may cause loops)
  • Useful for reacting to actual DOM changes
updated() {
  console.log("Component updated");
}

unmounted()

Executed when the component is removed

  • Clean up timers, listeners, sockets, etc.
  • Helps prevent memory leaks
unmounted() {
  console.log("Component removed");
}

Watch

Vue allows you to observe changes in reactive data and run custom logic.

Useful for asynchronous operations, API calls, validation, and reacting to specific changes.

Watch vs Computed

  • Computed: derived values, cached, reactive
  • Watch: runs a function whenever a value changes
  • Use computed for deriving values
  • Use watch for performing actions

Basic watcher

Watching a single data property

export default {
  data() {
    return { name: '' }
  },
  watch: {
    name(newVal, oldVal) {
      console.log("Name changed:", oldVal, "→", newVal)
    }
  }
}

Watch: async operations

Useful for API calls triggered by changes

watch: {
  searchQuery: async function (value) {
    const res = await fetch(`/api?q=${value}`)
    this.results = await res.json()
  }
}

Watch: debounced async operations

To avoid excessive API calls (e.g. during fast typing), use a debounce strategy.

Debouncing delays the execution until the user stops typing.

Watch: debounced async operations

let debounceTimer = null
watch: {
  searchQuery(value) {
    clearTimeout(debounceTimer)
    debounceTimer = setTimeout(async () => {
      if (!value) {
        this.results = []
        return
      }
      try {
        const res = await fetch(`/api?q=${encodeURIComponent(value)}`)
        this.results = await res.json()
      } catch (err) {
        console.error("API error:", err)
      }
    }, 400) /* wait 400ms */
  }
}

This prevents sending a request for every keystroke, improving performance and user experience.

Immediate & Deep Watchers

  • immediate: runs on initialization
  • deep: observes nested objects and arrays
watch: {
  settings: {
    handler(val) {
      console.log("Settings changed", val)
    },
    deep: true,
    immediate: true
  }
}

State Management

For larger apps, managing shared state becomes complex.

Vue provides libraries for centralized state management:

  • Vuex: older, more structured, inspired by Redux
  • Pinia: official state library for Vue 3

Why a store?

  • A single source of truth for shared data
  • Easier debugging
  • Predictable updates
  • Better organization for medium/large projects

Pinia basics

Pinia is the recommended store for Vue 3

import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', {
  state: () => ({
    count: 0
  }),
  actions: {
    increment() {
      this.count++
    }
  }
})

Using a Pinia store

import { useCounterStore } from './stores/counter'

export default {
  setup() {
    const counter = useCounterStore()

    return { counter }
  }
}
{{ counter.count }}

Vuex basics

Vuex uses a more rigid structure: state, mutations, actions, getters

const store = createStore({
  state() {
    return { count: 0 }
  },
  mutations: {
    increment(state) { state.count++ }
  },
  actions: {
    incrementAsync({ commit }) {
      setTimeout(() => commit('increment'), 1000)
    }
  }
})

Pinia vs Vuex

  • Pinia: simpler, more modern, uses Composition API
  • Vuex: structured but more verbose
  • Pinia is the recommended choice for new Vue 3 apps

MongoDB

MongoDB

Typical case of a web application: interacting with a database

The type of database is not important (SQL/NoSQL, doesn’t matter)

The pairing of Node.js and MongoDB comes “naturally”

MongoDB with Node.js

  • Connection
  • CRUD operations

We will use the mongodb module

Connection

Connection URI:

Source: MongoDB
  • MongoClient object to manage the connection
  • Exports a connect() promise that opens the connection
  • Should be closed in case of error or when operations are finished using close()
  • MongoClient returns the MongoDB database through db()
  • From the database you can access the collection via collection()

Connection

const { MongoClient } = require("mongodb");
const uri = "mongodb://localhost:27017";
const client = new MongoClient(uri);
async function connect() {
  try {
    await client.connect();
  } finally {
    await client.close();
  }
}
connect().catch(console.log);

CRUD Operations

  • Retrieving documents, returning either a single document or a FindCursor
    • Collection.find()
    • Collection.findOne()
    • Collection.aggregate()
  • Inserting documents
    • Collection.insert()
    • Collection.insertOne()
  • Updating documents; you can update (requires a filter) or replace
    • Collection.updateOne()
    • Collection.updateMany()
    • Collection.replaceOne()
  • Deleting documents
    • Collection.deleteMany()
    • Collection.deleteOne()

CRUD Operations

const query = { title: "Desired Title" };
const options = {
  sort: { "imdb.rating": -1 }
};
const movie = await movies.findOne(query, options);
const query = { runtime: { $lt: 15 } };
const options = {
  sort: { "imdb.rating": -1 }
};
const cursor = movies.find(query, options);
await cursor.forEach(console.dir);
console.log(await cursor.toArray());