Andrea De Lorenzo, University of Trieste
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 |
Telegram Channel
Some Numbers:
Principles, methods, and techniques of web programming
Practical Course, a lot of technologies:
In practice: how to create a web application
We will only use products available online, for free:
Programming Books:
Design Books:
Some details:
WARNING!!
The technologies we will see:
Final goal: teach how to fish, rather than give the fish.
Always evaluate:
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
much more complicated, actually
Important enhancements:
<!DOCTYPE html>
)
<article>
,
<section>
,
<nav>
,
<aside>
<audio>
,
<video>
Official reference on the differences
To ensure backward compatibility, some things may be allowed for HTML interpreters but not for authors
<!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>
<title>Hello HTML</title>
→
element
<title>
→ start tag
Hello HTML
→ content</title>
→ end tag
<a href="http://www.units.it">UniTs</a>
href="http://www.units.it"
→ attribute
href
→ attribute namehttp://www.units.it
→ attribute value
<img src="white-dog.png"/>
<br/>
<input type="checkbox" checked/>
<!--...-->
:
<!--nobody can see this-->
<head>
→ head, additional information about the document
<body>
→ informational content of the document
<title>
→ document title<meta name="..." content="...">
name="author"
→ document author
name="description"
→ document description
name="keywords"
→ document keywords ("...,...,..."
)
Browser: HTML → DOM tree → screen rendering
Tree representation of the document, in memory
Alternatives to the screen:
Different levels of correctness:
Elements can be nested but not overlapped
<p>Example <strong>correct</strong></p>
→ correct
<p>Example <strong>correct</p></strong>
→ invalid
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!
Special characters with a name:
↓
→
down arrow (↓)
ℚ
→ rationals
(ℚ)
Rules:
&s
if s is
the name of one of the characters
There are many more!
What to do?
The specification = THE manual = the bible:
HTML5 W3C Recommendation,
https://html.spec.whatwg.org/multipage/
What does it contain?
Also as an introduction to HTML
Example: start tag? end tag? />
?
The start and end tags of certain normal elements can be omitted, as described later
complicated, better to always include the end tag
Another example: <em>
em
element
… the teacher is familiar with the W3C Validator
Style → de gustibus?
Usability
they are not only about HTML (HTML ≠ representation)
<!-- -->
→ defines a comment<!DOCTYPE>
→ defines the document type
<a>
→ defines a hyperlink<abbr>
→ defines an abbreviation<address>
→ defines an address element
Complete 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 |
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 linksaside
→ a piece of content complementary to its context (e.g., notes, Twitter messages, etc.)
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)
h1
larger than that of
h2
?
section
elements larger than
that after an article
?
address
tag rendered?Wrong, you shouldn’t be asking yourself that!
Language used to describe the content and structure of the information in a web document
Not the representation!
<h2>My memoirs</h2>
<p>
I don’t remember them anymore...
</p>
p
→ paragraphhr
→ topic change (not needed between
sections)
pre
→ preformatted textblockquote
→ external quotationmain
→ main content of the page, not
repeated across the site. ⚠ only one per page!
<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>
ul
→ unordered listol
→ ordered listli
→ list item⚠ must not be placed inside paragraphs!
CR+LF
≠ new linebr
→ line 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)
em
→ the content of the element deserves emphasis
strong
→ the content is importantmark
→ highlighted text for reference (e.g., searched text)
s
→ the content is no longer accurate or relevant
sub
and sup
→ subscript and
superscript text
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.
code
→ the content is a piece of source code
samp
→ output produced by the codevar
→ a variablekbd
→ keyboard input... sort ofsamp
→ the key was pressed by the user and displayed on screen
samp
tag → a menu was selected
kbd
→ key combination
kbd
Please press
Ctrl + Shift + R
to reload a page.
Please press Ctrl + Shift + R to reload a page.
samp
in kbd
To create a new file, choose the menu option
File⇒New 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 File⇒New Document.
Don't forget to click the OK button to confirm once you've entered the name of the new file.
I go to the <a href="http://www.units.it">university</a>
a
→ link (anchor) to another document
href=""
→ location of the other document
href="udine.html"
href="http://www.units.it"
href="#people"
href="mailto:andrea.delorenzo@units.it"
link
is something else
<img src="white-dog.jpg" alt="The white dog"/>
src
→ location of the image resourcealt
→ fallback content:
content that is to be used when the external resource cannot be used
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=""
<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, headingthead
; tfoot
→ column labels; totals, etc. (header, footer)
tbody
→ body (with the values)tr
→ row (table row)td, th
→ cell (table data/header cell)
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 theclass
,lang
, andtitle
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
, ordir
. 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> < 256; <span class="ident">j</span>++) { <span class="ident">i_t3</span> = (<span class="ident">i_t3</span> & 0x1ffff) | (<span class="ident">j</span> << 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;
}
id
Attributeid
→ unique identifier
<section id="abstract">
It can be used for:
<a href="#abstract">
Identifiers are opaque strings. Particular meanings should not be derived from the value of the id attribute.
title
Attributetitle
→ 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.
lang
and translate
Attributeslang
→ 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>
data-
is the name of the
custom attribute
dir
and style
Attributesdir
→ text direction
style
→ appearance of the element, we’ll see later
<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
.
Write a (HTML-only) document about your city or neighborhood.
Content (items):
We will assess the syntactic, semantic, and stylistic correctness of the HTML document.
Rules:
aside
, i
, em
,
strong
, nav
, lang
,
li
Choose whichever you like, I suggest:
Recommended extensions:
Recommended packages:
Features:
Fewer plugins than VS Code or Sublime, but designed for speed and teamwork.
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?
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>
DOM tree:
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
: ⏎␣⏎Let’s consider the subtree of the node body
(some #text
omitted):
body
is the parent of the node h1
p
, #comment
, ... are sibling of the node h1
h1
, p
, ... are children of the node body
a
, h1
, p
, ... are descendant of the node body
body
, p
, h1
, a
are elements#text
are text (they have no children!)For each node of the DOM tree:
reading the document: "drawn" → "spoken", "where" → "when"
Imagine you are the browser, or that you have to write the browser program’s code...
Goal: DOM tree → boxes tree
Main transformation rules:
An element is drawn if and only if all the following conditions are valid:
Premise: types of boxes
What they can contain:
strong
element)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 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
Non-exhaustive list:
p
table
nav
div
form
main
, article
, section
h1
, h2
, ...Non-exhaustive list:
a
span
em
strong
input
, button
, textarea
img
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.
We’re missing something:
"box type", "margin", ... → style properties of boxes
A document that specifies which values to assign to which elements’ properties
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"
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
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.
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.
An ordered list of rules
does not apply only to HTML documents
selector { property-name: property-value; property-name: property-value; ... } selector { /* comment */ property-name: property-value; property-name: property-value; ... } /* comment */
The specification defines:
@
:
@charset
@import
@namespace
@media
@viewport
But we’ll talk about them later...
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
Three levels of correctness:
there is a CSS validator
Who defines the style?
Where do I specify that I want to use certain rules for a given HTML document d? Three methods:
<link rel="stylesheet" type="text/css" href="...">
style
element:
<style>...</style>
style
attribute of the element I want to style (the selector is not needed!):<p style="...">
@import
The @import
rule allows you to import other style sheets into a CSS code
@charset
is allowedExample: importing a Google Web Font
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet" >
font-family: 'Roboto', sans-serif;
All methods can be used together → they are all applied!
<link ...>
)
link
is also used for other purposes
If a property P is not defined for an element E, the element inherits the value of P from its parent (parent of E)
Inheritance → cascading style sheet
How do I compute the value of each property?
Six values for each property...
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.
What if multiple rules are in conflict?
style="..."
, most important)<style>
)<link>
)!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:
Example:
{ background-color: lightgrey !important; }
!important
!important
solves the problem!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;
}
Some keywords allow forcing certain behaviors:
initial
→ default valueinherit
→ taken from the parent elementunset
, revert
)An expression that, when applied to an element, returns a boolean
fselector(E) ∈ {true, false}
The specification describes all the possible functions f
*
→ 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
*
→ universal selectore
→ type selector (e.g., <div>
, <p>
).className
→ class selector#idName
→ ID selectorSelectors 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"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)e[a]
→ an <e>
with an attribute ae[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
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 parente: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 documente:empty
→ an <e>
without children, not even textnth-child
: detailse:nth-child(n)
: n
can be an expression that is a bit more complex:
e:nth-child(3)
→ the third childe:nth-child(even)
= e:nth-child(2n)
→ even childrene:nth-child(odd)
= e:nth-child(2n+1)
→ odd childrene:nth-child(5n+2)
→ the 2nd, 7th, 12th, ... childe: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
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>
content
property<p>Nel mezzo di cammin di nostra vita</p>
↓
<p><span::first-letter>N</span>el mezzo di cammin di nostra vita</p>
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
: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 selectore:has(f):has(g)
or e:has(f, g)
Support is limited to some browsers
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:
The larger the number, the higher the specificity.
A great example based on Star Wars.
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 |
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.
figure:has(figcaption) img {
outline: 10px dashed #8be9fd;
}
We will only see a few...
color
→ text colorbackground-color
→ background colorborder-color
→ border colorValues:
color: red;
→ by named color keyword (including extended color keywords)color: #ff0000;
→ hexadecimal RGB notationcolor: 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 channelcolor: transparent;
→ transparent keywordbackground-color
→ background colorbackground-image
→ background imagebackground-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)background
→ shorthand property for all background-related propertiesExample:
body {
background-image: url('img_tree.png');
background-repeat: no-repeat;
background-position: right top;
}
font-family
→ font family name / generic familyfont-size
→ absolute-size keyword | relative-size keyword | length | percentagefont-weight
→ font weight (normal, bold, 100–900)font-variant
→ small-caps variantfont-style
→ normal | italic | obliquefont
→ shorthand property for all font-related propertiesExample:
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
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 */
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.
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.
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;
}
They behave like variables
counter-reset: counterName;
counter-increment: counterName;
content
propertyExample:
body {
counter-reset: sectionCount;
}
h2::before {
counter-increment: sectionCount;
content: "Section " counter(sectionCount) ": ";
}
Defines how the box will be rendered
There are three possible values
Various options:
display
PropertySummarizes 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 boxdisplay: block
→ block flow → block-level boxdisplay: none
→ does not generate a boxdisplay: inline-block
→ inline flow-root → we’ll see laterdisplay: flex
→ block flex → we’ll see laterdisplay
has a major impact on the representation of a document!
visibility: visible
→ drawsvisibility: hidden
→ does not drawWarning:
visibility: hidden
→ the box takes up the expected space but is not visibledisplay: none
→ the box does not existWe use width
and height
:
max-width
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
But I can cheat:
box-sizing: border-box;
→ padding and borders are included
Hint: consider adding it in a * { }
block
How can I move the box?
position
property:
static
→ default, follows the normal flow; not affected by top/bottom/right/left and formally not positionedrelative
→ extra properties must be used (top, right, bottom, or left)
position: relative; top: -20px; left: 20px;
makes the second block overlap the first
How can I move the box?
position
property:
fixed
→ positioned relative to the browser window
absolute
→ behaves like fixed
but relative to the nearest positioned ancestor
<HTML>
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%;
}
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 floatsfloat: none
→ does not float (default)Ex: style="float: left; width: 200px;height: 100px;margin: 1em;"
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?
clear
clear: left
, clear: right
, clear: both
→ don’t align with floating boxes on the left and/or rightclear: none
→ allow alignment.clearfix {
overflow: auto;
zoom: 1; /* for IE6 */
}
float
and clear
: examplep {clear: left;}
img {float: left;}
float
and clear
At what point in the HTML document is the image inserted?
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 blockdisplay: inline-block
(some issues with IE6 and IE7)And I don’t need any clearing!
column
allows me to split text into columns
.three-column {
padding: 1em;
column-count: 3;
column-gap: 1em;
}
display: flex;
comes with CSS3 → not all browsers handle it well
It has several properties, which can be grouped by applicability:
flex-direction
: row | row-reverse | column | column-reverse
flex-direction
: row | row-reverse | column | column-reverse
flex-wrap
: nowrap (default) | wrap | wrap-reverse (bottom-top)
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-direction
: row | row-reverse | column | column-reverseflex-wrap
: nowrap (default) | wrap | wrap-reverse (bottom-top)justify-content
: flex-start | flex-end | center | space-between | space-around | space-evenlyalign-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)order
: <integer> → reorders the contentflex
: <integer> → how to share the space
align-self
: overrides the container’s valueSimply put: we make sure our website works well on every device.
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">
You can make certain rules apply only to specific media (or media with certain characteristics):
link
:
<link ... media="screen" href="css1.css"> <link ... media="print,tty" href="css2.css">
@media
:
@media print { /* style sheet for print goes here */ }
Some media: screen, print, handheld, braille, speech, tty, ...
We want a layout like this:
How can I switch between the three layouts or create the third one?
Slides inspired by the presentation of Morten Rand-Hendriksen
Terminology
display: grid;
Terminology
display: grid;
How is it used?
That's it!
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).
Spanning multiple cells
grid-column: x/y;
→ from vertical line X to Ygrid-row: x/y;
→ from horizontal line X to YProblem: working with numbers is tricky, it’s easy to get confused (though you can actually name the lines)
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;
}
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";
}
}
Some details:
@supports (grid-area: auto){...}
In practice:
Some useful references:
But does it always work?
NO!
And not only that — the problem also applies to other features (e.g., column
)
Solution: 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;
}
Do I always have to do everything manually?
No! I can get help
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
It’s worth reading the official guide
A CSS development tool written in JavaScript, usable
<link rel="stylesheet/less" type="text/css" href="styles.less" />
<script src="less.js" type="text/javascript"></script>
@red: #FF0000; a {color: @red}
→ a {color: #ff0000}
div{ width: 200px; p{ font-size: 20px; } }
→ div{ width: 200px;}
→ div p{ font-size: 20px;}
.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;}
.mixin(){ color: red; font-weight:bold; } p{ font-size:18px; .mixin; }
→ p{font-size: 18px; color: red; font-weight:bold;}
.mixin(@param){ color: @param; font-weight:bold; } p{ font-size:18px; .mixin(red); }
Using the HTML document from exercise HTML-1, write CSS that renders the document like a medieval illuminated manuscript.
Using the HTML document again: the content of each section
must be invisible by default and become visible under some user action.
For example:
only HTML and CSS
Some more changes:
section
→ @page
;
some help only HTML and CSS
I can ask the browser to execute compiled code (or code running on a VM)
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.
Execution of the author’s code in the context of the web document
Code? → JavaScript
... but not only
During execution, the code can access the DOM tree, and thus the information within the document
But also external resources (the window, storage, ...)
HTML Document → DOM tree → representation
Manipulating the DOM means changing the representation — in real time!
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
Note:
→ they don’t have a specific “when”...
It is executed when it is encountered
The browser reads (parses) the HTML document, and when it finds a script, it executes it
Two main methods:
<script type="text/javascript">
/* do something */
</script>
<script type="text/javascript" src="..."></script>
src
and Start of ExecutionFor 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
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:
<p onclick="/* piece of code */">click me!</p>
What will we learn?
Meanwhile:
Engine = pair (VM, dialect)
There are many:
Sophisticated: for example, JIT
We won’t go into detail
Some peculiarities:
boolean
, break
, delete
, extends
, static
, ... many unusedWe’ll see more as we go
5 basic immutable types:
null
undefined
All other values are objects (mutable): arrays, functions, regexes, and objects.
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 // → ???
typeof
: null
typeof null // → "object"!!!
But why???
In memory: 32 bits per value
Null
: dato = 0x00]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;
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 SyntaxRelaxed syntax...
Which ones work, and why?
typeof 1
?typeof(1)
?typeof (1)
?typeof
and SyntaxRelaxed syntax...
Which ones work, and why?
typeof 1
?typeof(1)
?typeof (1)
?typeof
is an operator, and what is inside the parentheses is an expression to be evaluated.
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!
There is only one number type: float (IEEE 754 Double Precision)
Remember the issues this causes?
There is only one number type: float (IEEE 754 Double Precision)
0.1 + 0.2 == 0.3 /* → false */
9999999999999999 == 10000000000000000 /* → true */
null
vs undefined
An identifier refers to:
undefined
if no value (other than undefined
) has been assigned to itnull
only if it has been explicitly assigned null
Why do both exist? Is there a reason?
An object is a mutable collection of properties.
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
statementvar simba = {
name: "simba",
animalType: "dog",
legs: 4,
"sound": "bark"
}
simba
as visible within the scope.What is the scope? We’ll see.
simba.name
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.
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...
var name = simba.name;
If it’s not defined, the value is undefined
.
simba.nickname = "White dog";
If it’s not defined, it’s added; otherwise, it’s modified.
delete simba.nickname;
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"}
var simba = { name: "simba", legs: 4 }; for (var propName in simba) { console.log("simba." + propName + " = " + simba[propName] + ", of type " + (typeof simba[propName])); }
A function is an object with two additional hidden properties:
typeof f
returns "function"
if f
is a function.
Here is the sixth element.
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.
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.
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:
function summation(a, b) {
return a + b;
}
summation.name /* → "summation" */
Named function — summation
is defined and refers to the function.
Functions are objects, i.e. mutable collections of properties!
var sum = function(a, b) {
return a + b;
}
sum.p = "hello";
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!
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!
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();
};
var
defines a variable; if omitted, it implies the global scope.
var a;
→ a
is defined (but uninitialized) in the local scopevar a = 0;
→ a
is defined and refers to 0 in the local scopea = 0;
a
was defined in a parent scope, it now refers to 0Watch 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 looptop
becomes a global variable (in a browser: the top-level window
object)top
is not a number)var
declares the variable in the function scope.
And if I want one at the block level?
Since ECMAScript 6 you can use: let
There are four Function Invocation Patterns:
What changes?
this
arguments
this
depends on the invocation pattern.If and only if:
this
is the object containing itundefined
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
this
this
is not optional!
given the same semantics.
When the function is not a property of an object and is invoked directly:
var sum = add(3, 4); // sum is 7
this
is the global object.window
object.this
of the outer function!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); /* → ?? */
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 */
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.
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 */
new
)If a function is called with the keyword new
:
this
is a new objectthis
is returnedThe new object has a hidden link to the function’s prototype
property.
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.
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");
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");
weirdDog
? → undefined!
arguments
arguments
is a (quasi) array
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, "
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.
arguments
var surpriseMe = function (a) {
console.log(a + " - " + arguments[0]);
a = 3;
console.log(a + " - " + arguments[0]);
};
surpriseMe(2)
?
2 - 2 3 - 3
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
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;
}
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, "
Functions always have a return value.
undefined
.Execution (obviously) stops when the return statement is reached.
return
and whitespaceThe 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 whitespaceIt is not equivalent to
var f = function() {
return {word: "hello"};
}
which, in turn, is equivalent to
var f = function() {
return {
word: "hello"
};
}
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;
};
var fun = function() {
var a = 1;
var innerFun = function() {
console.log(a);
};
innerFun();
};
fun() /* prints 1: all good */
var fun = function() {
var a = 1;
var innerFun = function() {
console.log(a);
var a = 2;
};
innerFun();
};
fun() /* prints undefined!!! */
Why?
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?
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
.
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');
};
};
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?
foo
is hoisted.How can we expose functionality without exposing internal variables?
Let’s take a counter:
var counter = 0;
function add() {
counter += 1;
}
add();
add();
add();
add()
can also modify counter
.What if we put the variable inside the function?
var counter = 0;
function add() {
var counter;
counter += 1;
}
add();
add();
add();
counter
is 0.What if we remove the global variable and just return the value?
function add() {
var counter;
counter += 1;
return counter;
}
add();
add();
add();
counter
is 1.Let’s try nesting functions:
function add() {
var counter = 0;
function plus() { counter += 1; }
plus();
return counter;
}
plus
has access to the enclosing scope, and therefore to counter
.plus()
from outside?A self-invoking function:
var add = (function () {
var counter = 0;
return function () {
counter += 1;
return counter;
}
})();
add(); /* 1 */
add(); /* 2 */
add(); /* 3 */
counter
? No.var add = (function () {
var counter = 0;
return function () {
counter += 1;
return counter;
}
})();
add(); add(); add();
add
contains the result of a self-invoking function.add
is itself a function → it has access to the scope that contains it → it can access counter
, which still exists.counter
.We can also create more advanced closures:
var counter = function() {
var n;
n = 0;
return {
inc: function() {
n = n + 1;
return n;
}
};
}();
counter.inc();
inc
is a closure.n
is an enclosed variable.Some operators also apply to unexpected types: it's useful to know how things work to avoid surprises.
Operator +
:
often the source of unpleasant issues when reading a number from the DOM
Every value in JS also has an implicit boolean value:
We can use a function to test it:
function truthyOrFalsy(a) {
return a ? "truthy" : "falsy";
}
truthyOrFalsy(0)
→ falsytruthyOrFalsy(10 == 5)
→ falsytruthyOrFalsy(1)
→ truthytruthyOrFalsy(-1)
→ truthytruthyOrFalsy({})
→ truthyThere are some values that are truthy but == false
"0" == false
:
==
→ converts the string to a number0 == false
"0" == 0
"0" == false
Operator ===
:
Operator ==
: tries to perform type conversion
false == undefined /* false */
false == null /* false */
null == undefined /* true */
Goodbye transitivity of equality: better === than == !
An array is an object that:
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,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');
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
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'));
};
length
property?splice
function?length
appear in a for ... in
?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;
});
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)!
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*/
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
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
Traditionally (Java, C++, C#) there are two entities: classes and instances.
In addition:
JavaScript is loosely-typed: every object derives from another object from which it inherits properties, called its prototype.
How is this achieved?
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__
undefined
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;
}
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;
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
→ ""An object’s prototype is itself an object, so if you
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*/
Object
Function
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
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"*/
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
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*/
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*/
Object.create = function(o) {
var F = function () {};
F.prototype = o;
return new F();
};
Object
create
is invoked with argument o
F
o
new F()
(a new object with a hidden link to the prototype
property of the creating function, that is o
)
Object.create = function(o) {
...
};
Object
Augmenting a base type (Object
)
This can also be done with strings, numbers, etc...
String.reverse = function() {
...
};
don’t overuse it
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" */
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!
Object.prototype.version = "7.2.11";
"uh".version; /* → 7.2.11*/
Why? Isn’t "uh"
a primitive String?
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.
So, can I add properties to primitives?
var primitive = "september";
primitive.vowels = 3;
primitive.vowels; /* → ??*/
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*/
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?
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();
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.
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*/
Remember?
Tree representation of the document, in memory
Programmatic interface for:
Essentially, it connects web pages to scripts or programming languages.
HTMLDocument
: extends Document
, but with HTML5 many methods/properties are already included in it.HTMLElement
: for all types
HTMLAnchorElement
HTMLParagraphElement
HTMLFormElement
Not just HTML! There’s also the entire world of SVG...
The document
object contains the DOM:
document.getElementById("...")
→ returns the element (HTMLElement
) with the specified IDdocument.getElementsByTagName("...")
→ returns the elements with the specified tag name ("a"
, "span"
, ...);
"*" returns all of themdocument.getElementsByClassName("...")
→ returns the elements with the specified class (a list of space-separated values)document.querySelectorAll("...")
→ returns all elements matching the given CSS selectordocument.querySelector("...")
→ returns the first element matching the given CSS selectordocument.createElement("...")
→ creates an element of the specified typeelement.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 descendantsvar mainSection = document.getElementById("mainSection");
var newP = document.createElement("p");
newP.innerHTML = "this is the <b>new</b> paragraph";
mainSection.appendChild(newP);
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 elementThere are several ways to bind to events:
<button onclick="alert('Hello world!')">
Ugly:
There are several ways to bind to events:
/* 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.
There are several ways to bind to events:
/* Assume myButton is a Button */
myButton.onclick = function(event){
alert('Hello world');
};
Note: only one handler per element per event.
There are three phases:
td
)bubble
Manually stop bubbling propagation:
ev.stopPropagation();
Note: this does not stop the function’s execution.
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