-
Notifications
You must be signed in to change notification settings - Fork 0
/
javascript-and-the-browser.html
275 lines (256 loc) · 50.2 KB
/
javascript-and-the-browser.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
<!DOCTYPE html><html lang="de-ch"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><title>JavaScript and the browser - Finecloud</title><meta name="description" content="The DOM Based on the received HTML document the browser builds up a model of the document structure, the Document Object Model (DOM) The DOM has a tree structure and each node of the document is represented by an object The browser renders the page…"><meta name="generator" content="Publii Open-Source CMS for Static Site"><link rel="stylesheet" href="https://www.finecloud.ch/media/plugins/syntaxHighlighter/prism-black.css"><link rel="canonical" href="https://www.finecloud.ch/javascript-and-the-browser.html"><link rel="alternate" type="application/atom+xml" href="https://www.finecloud.ch/feed.xml"><link rel="alternate" type="application/json" href="https://www.finecloud.ch/feed.json"><meta property="og:title" content="JavaScript and the browser"><meta property="og:site_name" content="Finecloud"><meta property="og:description" content="The DOM Based on the received HTML document the browser builds up a model of the document structure, the Document Object Model (DOM) The DOM has a tree structure and each node of the document is represented by an object The browser renders the page…"><meta property="og:url" content="https://www.finecloud.ch/javascript-and-the-browser.html"><meta property="og:type" content="article"><link rel="shortcut icon" href="https://www.finecloud.ch/media/website/finecloud.png" type="image/png"><link rel="stylesheet" href="https://www.finecloud.ch/assets/css/style.css?v=39da73365516a098a9b73b721fc970e2"><script type="application/ld+json">{"@context":"http://schema.org","@type":"Article","mainEntityOfPage":{"@type":"WebPage","@id":"https://www.finecloud.ch/javascript-and-the-browser.html"},"headline":"JavaScript and the browser","datePublished":"2023-01-24T08:35","dateModified":"2023-03-29T20:14","description":"The DOM Based on the received HTML document the browser builds up a model of the document structure, the Document Object Model (DOM) The DOM has a tree structure and each node of the document is represented by an object The browser renders the page…","author":{"@type":"Person","name":"Finecloud","url":"https://www.finecloud.ch/authors/finecloud/"},"publisher":{"@type":"Organization","name":"Finecloud"}}</script><meta name="google-site-verification" content="seFY9U12uiEq5U3_MyZiX6XWzk0AVFl9zITr2ZKsytY"></head><body><div class="site-container"><header class="top" id="js-header"><a class="logo" href="https://www.finecloud.ch/">Finecloud</a><nav class="navbar js-navbar"><button class="navbar__toggle js-toggle" aria-label="Menu" aria-haspopup="true" aria-expanded="false"><span class="navbar__toggle-box"><span class="navbar__toggle-inner">Menu</span></span></button><ul class="navbar__menu"><li><a href="https://www.finecloud.ch/" target="_self">Blog</a></li><li><a href="https://www.finecloud.ch/tags/" target="_self">Tags</a></li></ul></nav><div class="search"><div class="search__overlay js-search-overlay"><div class="search__overlay-inner"><form action="https://www.finecloud.ch/search.html" class="search__form"><input class="search__input js-search-input" type="search" name="q" placeholder="search..." aria-label="search..." autofocus="autofocus"></form><button class="search__close js-search-close" aria-label="Close">Close</button></div></div><button class="search__btn js-search-btn" aria-label="Search"><svg role="presentation" focusable="false"><use xlink:href="https://www.finecloud.ch/assets/svg/svg-map.svg#search"/></svg></button></div></header><main><article class="post"><div class="hero"><figure class="hero__image hero__image--overlay"><img src="https://www.finecloud.ch/media/website/download.jpg" srcset="https://www.finecloud.ch/media/website/responsive/download-xs.jpg 300w, https://www.finecloud.ch/media/website/responsive/download-sm.jpg 480w, https://www.finecloud.ch/media/website/responsive/download-md.jpg 768w, https://www.finecloud.ch/media/website/responsive/download-lg.jpg 1024w, https://www.finecloud.ch/media/website/responsive/download-xl.jpg 1360w, https://www.finecloud.ch/media/website/responsive/download-2xl.jpg 1600w" sizes="100vw" loading="eager" alt=""></figure><header class="hero__content"><div class="wrapper"><div class="post__meta"><time datetime="2023-01-24T08:35">Januar 24, 2023</time></div><h1>JavaScript and the browser</h1></div></header></div><div class="wrapper post__entry"><div class="post__toc"><h3>Table of Contents</h3><ul><li><a href="#mcetoc_1go1k7l5mfr">The DOM</a><ul><li><a href="#mcetoc_1go1k7l5mfs">The DOM Tree</a></li></ul></li><li><a href="#mcetoc_1go1k7l5mft">Finding Elements</a></li><li><a href="#mcetoc_1go1k7l5mfu">Element nodes</a></li><li><a href="#mcetoc_1go1k7l5mfv">Manipulating the DOM</a></li><li><a href="#mcetoc_1go1k7l5mg0">Animation</a></li><li><a href="#mcetoc_1go1k7l5mg1">Event handling</a><ul><li><a href="#mcetoc_1go1kdqqcj7">Event Object</a></li><li><a href="#mcetoc_1go1kdqqcj8">Event Propagation</a></li><li><a href="#mcetoc_1go1kdqqcj9">Default action</a></li></ul></li><li><a href="#mcetoc_1go387fbq1bm">AJAX</a><ul><li><a href="#mcetoc_1go387fbq1bn">AJAX and JSON</a></li><li><a href="#mcetoc_1go387fbq1bo">Same-Origin Policy</a></li></ul></li><li><a href="#mcetoc_1go387fbq1bp">jQuery</a><ul><li><a href="#mcetoc_1go387fbq1bq">jQuery usage</a></li><li><a href="#mcetoc_1go387fbq1br">The jQuery Object</a></li><li><a href="#mcetoc_1go387fbq1bs">jQuery and AJAX</a></li></ul></li></ul></div><h2 id="mcetoc_1go1k7l5mfr">The DOM</h2><ul><li>Based on the received HTML document the browser builds up a model of the document structure, the Document Object Model (DOM)</li><li>The DOM has a tree structure and each node of the document is represented by an object</li><li>The browser renders the page based on the DOM and provides an API to read and modify the DOM with JS</li><li>The DOM is live, i.e., DOM modifications are immediately reflected on the page</li></ul><h3 id="mcetoc_1go1k7l5mfs">The DOM Tree</h3><pre class="hljs" style="color: #a9b7c6; background: #282b2e; display: block; overflow-x: auto; padding: 0.5em;"><span class="xml"><span class="hljs-meta" style="color: #bbb529;"><!doctype html></span>
<span class="hljs-tag"><<span class="hljs-name" style="color: #e8bf6a;">html</span>></span>
<span class="hljs-tag"> <<span class="hljs-name" style="color: #e8bf6a;">head</span>></span>
<span class="hljs-tag"> <<span class="hljs-name" style="color: #e8bf6a;">title</span>></span>Todo App<span class="hljs-tag"></<span class="hljs-name" style="color: #e8bf6a;">title</span>></span>
<span class="hljs-tag"> </<span class="hljs-name" style="color: #e8bf6a;">head</span>></span>
<span class="hljs-tag"> <<span class="hljs-name" style="color: #e8bf6a;">body</span>></span>
<span class="hljs-tag"> <<span class="hljs-name" style="color: #e8bf6a;">h1</span>></span>Todo App<span class="hljs-tag"></<span class="hljs-name" style="color: #e8bf6a;">h1</span>></span>
<span class="hljs-tag"> <<span class="hljs-name" style="color: #e8bf6a;">p</span>></span>Don't forget anything!<span class="hljs-tag"></<span class="hljs-name" style="color: #e8bf6a;">p</span>></span>
<span class="hljs-tag"> <<span class="hljs-name" style="color: #e8bf6a;">p</span>></span>Please <span class="hljs-tag"><<span class="hljs-name" style="color: #e8bf6a;">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string" style="color: #6a8759;">"/login"</span>></span>login<span class="hljs-tag"></<span class="hljs-name" style="color: #e8bf6a;">a</span>></span>.<span class="hljs-tag"></<span class="hljs-name" style="color: #e8bf6a;">p</span>></span>
<span class="hljs-tag"> </<span class="hljs-name" style="color: #e8bf6a;">body</span>></span>
<span class="hljs-tag"></<span class="hljs-name" style="color: #e8bf6a;">html</span>></span></span></pre><p>the Tree Structure of the html above:</p><figure class="post__image"><img loading="lazy" src="https://www.finecloud.ch/media/posts/77/Screenshot-2023-01-24-at-10.45.34.png" alt="" width="1434" height="858" sizes="100vw" srcset="https://www.finecloud.ch/media/posts/77/responsive/Screenshot-2023-01-24-at-10.45.34-xs.png 300w, https://www.finecloud.ch/media/posts/77/responsive/Screenshot-2023-01-24-at-10.45.34-sm.png 480w, https://www.finecloud.ch/media/posts/77/responsive/Screenshot-2023-01-24-at-10.45.34-md.png 768w, https://www.finecloud.ch/media/posts/77/responsive/Screenshot-2023-01-24-at-10.45.34-lg.png 1024w, https://www.finecloud.ch/media/posts/77/responsive/Screenshot-2023-01-24-at-10.45.34-xl.png 1360w, https://www.finecloud.ch/media/posts/77/responsive/Screenshot-2023-01-24-at-10.45.34-2xl.png 1600w"></figure><p>you can traverse the DOM Tree with:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-comment" style="color: grey;">// Root node of the dom tree (html)</span>
<span class="hljs-keyword" style="color: #cc7832;">const</span> root = <span class="hljs-built_in">document</span>.documentElement;
<span class="hljs-comment" style="color: grey;">// The child elements of a node (only element nodes, no text nodes)</span>
<span class="hljs-comment" style="color: grey;">// -> HTMLCollection(2) [head, body]</span>
root.children;
<span class="hljs-comment" style="color: grey;">// head and body can also be accessed directly</span>
<span class="hljs-keyword" style="color: #cc7832;">const</span> head = <span class="hljs-built_in">document</span>.head;
<span class="hljs-keyword" style="color: #cc7832;">const</span> body = <span class="hljs-built_in">document</span>.body;
<span class="hljs-comment" style="color: grey;">// All children of a node (including text nodes)</span>
<span class="hljs-comment" style="color: grey;">// -> NodeList(7) [\#text, h1, \#text, p, \#text, p, \#text]</span>
body.childNodes;
<span class="hljs-comment" style="color: grey;">// Accessing children and node type</span>
body.childNodes[<span class="hljs-number" style="color: #6897bb;">0</span>].nodeType === Node.TEXT_NODE; <span class="hljs-comment" style="color: grey;">// \#text</span>
body.childNodes[<span class="hljs-number" style="color: #6897bb;">1</span>].nodeType === Node.ELEMENT_NODE; <span class="hljs-comment" style="color: grey;">// h1</span>
body.firstChild; <span class="hljs-comment" style="color: grey;">// \#text</span>
body.firstElementChild; <span class="hljs-comment" style="color: grey;">// h1</span>
<span class="hljs-comment" style="color: grey;">// dito for last: lastChild, lastElementChild</span>
</pre><p>Another example:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-keyword" style="color: #cc7832;">const</span> h1 = <span class="hljs-built_in">document</span>.body.children[<span class="hljs-number" style="color: #6897bb;">0</span>];
<span class="hljs-comment" style="color: grey;">// Parent node</span>
h1.parentNode;
<span class="hljs-comment" style="color: grey;">// Siblings</span>
h1.nextSibling; <span class="hljs-comment" style="color: grey;">// \#text</span>
h1.nextElementSibling; <span class="hljs-comment" style="color: grey;">// p</span>
<span class="hljs-comment" style="color: grey;">// dito for previous: previousSibling, previousElementSibling</span>
<span class="hljs-comment" style="color: grey;">// Example of recursively traversing the DOM</span>
<span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">function</span> <span class="hljs-title" style="color: #ffc66d;">findAnchors</span>(<span class="hljs-params">node</span>) </span>{
<span class="hljs-keyword" style="color: #cc7832;">if</span> (node.tagName === <span class="hljs-string" style="color: #6a8759;">'A'</span>) {
<span class="hljs-built_in">console</span>.log(node.textContent+<span class="hljs-string" style="color: #6a8759;">": "</span>+node.pathname);
}
<span class="hljs-keyword" style="color: #cc7832;">if</span> (node.nodeType === Node.ELEMENT_NODE) {
<span class="hljs-keyword" style="color: #cc7832;">for</span> (<span class="hljs-keyword" style="color: #cc7832;">let</span> i = <span class="hljs-number" style="color: #6897bb;">0</span>; i < node.children.length; i++) {
findAnchors(node.children[i]);
}
}
}
findAnchors(<span class="hljs-built_in">document</span>.body);
</pre><h2 id="mcetoc_1go1k7l5mft">Finding Elements</h2><p>It is often not a good idea to access a specific node by a fixed path since the document structure may change over time:</p><pre>// Get the href attribute of the first anchor<br>document.body.childNodes[5].childNodes[1].href;</pre><p>There are a number of functions to find DOM elements in a more sophisticated way. The functions can be called on the document or on any element node to reduce the search on the node’s descendants</p><pre>// Get the href attribute of the first anchor<br>document.getElementsByTagName('a')[0].href;</pre><p>more examples of finding elements:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-comment" style="color: grey;">// Get a HTMLCollection of nodes by tag name</span>
<span class="hljs-built_in">document</span>.getElementsByTagName(<span class="hljs-string" style="color: #6a8759;">'a'</span>);
<span class="hljs-comment" style="color: grey;">// Get a HTMLCollection of nodes by class name</span>
<span class="hljs-built_in">document</span>.getElementsByClassName(<span class="hljs-string" style="color: #6a8759;">'external-link'</span>);
<span class="hljs-comment" style="color: grey;">// A single node can be retrieved by id (only via document)</span>
<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string" style="color: #6a8759;">'logo'</span>);
<span class="hljs-comment" style="color: grey;">// Elements can also be selected by using a CSS selector string</span>
<span class="hljs-comment" style="color: grey;">// A static NodeList is returned</span>
<span class="hljs-built_in">document</span>.querySelectorAll(<span class="hljs-string" style="color: #6a8759;">'p a.external-link'</span>);
<span class="hljs-comment" style="color: grey;">// Like querySelectorAll but only the first matching node is returned</span>
<span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string" style="color: #6a8759;">'#logo'</span>);
</pre><h2 id="mcetoc_1go1k7l5mfu">Element nodes</h2><ul><li>For different HTML elements (body, div, p, a, etc.) different objects with different properties and methods are created</li><li>For example, an anchor object has a href and pathname property, whereas a form object has a submit and reset method</li><li>w3schools provides a nice reference http://www.w3schools.com/jsref/default.asp</li></ul><pre class="hljs" style="color: #a9b7c6; background: #282b2e; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-keyword" style="color: #cc7832;">const</span> a = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string" style="color: #6a8759;">'a'</span>);
<span class="hljs-built_in">console</span>.log(a.href);
<span class="hljs-comment" style="color: grey;">// -> ’https://www.todo-app.com/login’</span>
<span class="hljs-built_in">console</span>.log(a.pathname);
<span class="hljs-comment" style="color: grey;">// -> ’/login’</span>
<span class="hljs-keyword" style="color: #cc7832;">const</span> f = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string" style="color: #6a8759;">'myForm'</span>);
f.reset();
<span class="hljs-comment" style="color: grey;">// -> resets all fields of the form</span>
f.submit();
<span class="hljs-comment" style="color: grey;">// -> submits the form</span></pre><h2 id="mcetoc_1go1k7l5mfv">Manipulating the DOM</h2><ul><li>Almost everything in the DOM can be manipulated with JavaScript:<ul><li>Single node properties can be changed</li><li>Nodes can be moved within the tree</li><li>Nodes can be removed </li><li>New nodes can be added</li></ul></li></ul><pre class="hljs" style="color: #a9b7c6; background: #282b2e; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-keyword" style="color: #cc7832;">const</span> h1 = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string" style="color: #6a8759;">'h1'</span>);
<span class="hljs-comment" style="color: grey;">// Change the color style property to ’#FF0000’</span>
h1.style.color = <span class="hljs-string" style="color: #6a8759;">'#FF0000'</span>;
<span class="hljs-comment" style="color: grey;">// Change the display style property to ’none’</span>
h1.style.display = <span class="hljs-string" style="color: #6a8759;">'none'</span>;
<span class="hljs-comment" style="color: grey;">// Change the text of the h1</span>
h1.childNodes[<span class="hljs-number" style="color: #6897bb;">0</span>].nodeValue = <span class="hljs-string" style="color: #6a8759;">"Hello Earth!"</span>;
<span class="hljs-comment" style="color: grey;">// Or more comfortable by using the textContent property (all children of h1</span>
<span class="hljs-comment" style="color: grey;">// are removed and and a new text node with the respective text is added)</span>
h1.textContent = <span class="hljs-string" style="color: #6a8759;">"Hello World!"</span>;</pre><p>another example:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-keyword" style="color: #cc7832;">const</span> myList = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string" style="color: #6a8759;">'ul'</span>);
<span class="hljs-comment" style="color: grey;">// Nodes can be moved by simply re-inserting them at a different position</span>
<span class="hljs-comment" style="color: grey;">// -> The last node of the list is moved to the beginning of the list</span>
myList.insertBefore(myList.lastElementChild, myList.firstElementChild);
<span class="hljs-comment" style="color: grey;">// An element is removed by calling remove() on the node</span>
<span class="hljs-comment" style="color: grey;">// -> Removes the last element from the list</span>
myList.lastElementChild.remove();
<span class="hljs-comment" style="color: grey;">// New element and text nodes can be created. Newly created nodes must be</span>
<span class="hljs-comment" style="color: grey;">// added to the DOM tree explicitly. e.g. using appendChild()</span>
<span class="hljs-comment" style="color: grey;">// -> Creates a new list item and appends it to the end of the list</span>
<span class="hljs-keyword" style="color: #cc7832;">const</span> li = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string" style="color: #6a8759;">'li'</span>);
li.appendChild(<span class="hljs-built_in">document</span>.createTextNode(<span class="hljs-string" style="color: #6a8759;">"New item"</span>));
myList.appendChild(li);
<span class="hljs-comment" style="color: grey;">// Nodes can also be created implicitly by using the innerHTML property</span>
li.innerHTML = <span class="hljs-string" style="color: #6a8759;">"An <b>important</b> item"</span>;</pre><h2 id="mcetoc_1go1k7l5mg0">Animation</h2><ul><li>The setTimeout function waits a given number of milliseconds and then calls a function</li><li>setTimeout can be used to implement an animation</li></ul><pre class="hljs" style="color: #a9b7c6; background: #282b2e; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-comment" style="color: grey;">// The background color shall change between red and blue every second</span>
<span class="hljs-keyword" style="color: #cc7832;">const</span> ball = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string" style="color: #6a8759;">'#ball'</span>);
<span class="hljs-keyword" style="color: #cc7832;">let</span> toggle = <span class="hljs-literal" style="color: #6897bb;">false</span>;
<span class="hljs-comment" style="color: grey;">// The animation function</span>
<span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">function</span> <span class="hljs-title" style="color: #ffc66d;">animate</span>() </span>{
ball.style.backgroundColor = toggle ? <span class="hljs-string" style="color: #6a8759;">'#f00'</span> : <span class="hljs-string" style="color: #6a8759;">'#00f'</span>;
toggle = !toggle;
<span class="hljs-comment" style="color: grey;">// Keep the animation runnning</span>
setTimeout(animate, <span class="hljs-number" style="color: #6897bb;">1000</span>);
}
<span class="hljs-comment" style="color: grey;">// Start the animation</span>
setTimeout(animate, <span class="hljs-number" style="color: #6897bb;">1000</span>);</pre><ul><li>setInterval is similar to setTimeout but calls the function every interval and not only once</li><li>clearInterval and clearTimeout clear a timer set with setInterval and setTimeout respectively</li></ul><pre class="hljs" style="color: #a9b7c6; background: #282b2e; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-keyword" style="color: #cc7832;">const</span> ball = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string" style="color: #6a8759;">'#ball'</span>);
<span class="hljs-keyword" style="color: #cc7832;">let</span> toggle = <span class="hljs-literal" style="color: #6897bb;">false</span>;
<span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">function</span> <span class="hljs-title" style="color: #ffc66d;">animate</span>() </span>{
ball.style.backgroundColor = toggle ? <span class="hljs-string" style="color: #6a8759;">'#f00'</span> : <span class="hljs-string" style="color: #6a8759;">'#00f'</span>;
toggle = !toggle;
}
<span class="hljs-comment" style="color: grey;">// Start the animation</span>
<span class="hljs-keyword" style="color: #cc7832;">const</span> id = setInterval(animate, <span class="hljs-number" style="color: #6897bb;">1000</span>);
<span class="hljs-comment" style="color: grey;">// Stop the animation after 10s</span>
setTimeout(<span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">function</span>()</span>{
clearInterval(id);
}, <span class="hljs-number" style="color: #6897bb;">10000</span>);</pre><ul><li>For smooth animations use requestAnimationFrame</li><li>The scheduled animation function is called when the browser is ready to repaint the screen (at a rate of about 60 times per second but only when the window/tab is active)</li><li>By using requestAnimationFrame the browser can optimize concurrent animations</li></ul><pre class="hljs" style="color: #a9b7c6; background: #282b2e; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-keyword" style="color: #cc7832;">const</span> ball = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string" style="color: #6a8759;">'#ball'</span>);
<span class="hljs-keyword" style="color: #cc7832;">let</span> angle = <span class="hljs-built_in">Math</span>.PI / <span class="hljs-number" style="color: #6897bb;">2</span>;
<span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">function</span> <span class="hljs-title" style="color: #ffc66d;">animate</span>(<span class="hljs-params">time, lastTime</span>) </span>{
<span class="hljs-keyword" style="color: #cc7832;">if</span> (lastTime) {
<span class="hljs-comment" style="color: grey;">// Compute the next position based on the elapsed time</span>
angle += (time - lastTime) * <span class="hljs-number" style="color: #6897bb;">0.001</span>;
}
ball.style.left = (<span class="hljs-built_in">Math</span>.cos(angle) * <span class="hljs-number" style="color: #6897bb;">200</span>) + <span class="hljs-string" style="color: #6a8759;">'px'</span>;
requestAnimationFrame(<span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">function</span>(<span class="hljs-params">newTime</span>) </span>{ animate(newTime, time); });
}
requestAnimationFrame(animate);</pre><h2 id="mcetoc_1go1k7l5mg1">Event handling</h2><ul><li>Normally, a GUI must not only provide data to the user but also react to user input </li><li>A user interacts with the GUI by key strokes, mouse clicks, mouse moves, etc.</li><li>There are also implicit user interactions like window scrolling, window resizing, etc.</li><li>To react programmatically to user input, one could constantly read the state of the input device or adopt a polling mechanism</li><li>A better approach is a system that actively notifies registered listeners, also called handlers, about user inputs by firing events</li><li>Event handlers are registered for a certain event type using addEventListener and removed using removeEventListener</li><li>Event handlers are always registered in a context and are only called for events in that context</li><li>Event handlers can be registered on the window or on any DOM element</li><li>Multiple handlers can be registered for the same event and the same handler can be registered for multiple events</li></ul><pre class="hljs" style="color: #a9b7c6; background: #282b2e; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-comment" style="color: grey;">// An event handler can be registerd for a certain event type</span>
<span class="hljs-built_in">window</span>.addEventListener(<span class="hljs-string" style="color: #6a8759;">'click'</span>, <span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">function</span>() </span>{
<span class="hljs-built_in">console</span>.log(<span class="hljs-string" style="color: #6a8759;">"That's amazing!"</span>);
});
<span class="hljs-built_in">window</span>.addEventListener(<span class="hljs-string" style="color: #6a8759;">'resize'</span>, <span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">function</span>() </span>{
<span class="hljs-built_in">console</span>.log(<span class="hljs-string" style="color: #6a8759;">"Window has been resized"</span>);
});
<span class="hljs-comment" style="color: grey;">// Event handlers can be registerd on DOM elements to confine the context</span>
<span class="hljs-keyword" style="color: #cc7832;">const</span> myButton = docuemnt.querySelector(<span class="hljs-string" style="color: #6a8759;">'#my-button'</span>);
myButton.addEventListener(<span class="hljs-string" style="color: #6a8759;">'click'</span>, <span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">function</span>()</span>{
<span class="hljs-built_in">console</span>.log(<span class="hljs-string" style="color: #6a8759;">'What a surprise!'</span>);
});
<span class="hljs-comment" style="color: grey;">// Event handlers can also be removed again</span>
<span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">function</span> <span class="hljs-title" style="color: #ffc66d;">once</span>() </span>{
<span class="hljs-built_in">console</span>.log(<span class="hljs-string" style="color: #6a8759;">'Done.'</span>);
<span class="hljs-built_in">window</span>.removeEventListener(<span class="hljs-string" style="color: #6a8759;">'click'</span>, once);
}
<span class="hljs-built_in">window</span>.addEventListener(<span class="hljs-string" style="color: #6a8759;">'click'</span>, once);</pre><h3 id="mcetoc_1go1kdqqcj7">Event Object</h3><ul><li>Most events are propagated through the DOM tree, thus event handlers registered on an ancestor nodes are called too</li><li>Default propagation behaviour is bubbling (the more specific handler, the earlier it is called)</li><li>Handlers can also be registered in the capturing phase (before the bubbling phase)</li><li>The propagation of an event can be stopped by any handler by calling stopPropagation on the event object</li></ul><figure class="post__image"><img loading="lazy" src="https://www.finecloud.ch/media/posts/77/Pasted-image-20230130160641.png" alt="" width="421" height="229" sizes="100vw" srcset="https://www.finecloud.ch/media/posts/77/responsive/Pasted-image-20230130160641-xs.png 300w, https://www.finecloud.ch/media/posts/77/responsive/Pasted-image-20230130160641-sm.png 480w, https://www.finecloud.ch/media/posts/77/responsive/Pasted-image-20230130160641-md.png 768w, https://www.finecloud.ch/media/posts/77/responsive/Pasted-image-20230130160641-lg.png 1024w, https://www.finecloud.ch/media/posts/77/responsive/Pasted-image-20230130160641-xl.png 1360w, https://www.finecloud.ch/media/posts/77/responsive/Pasted-image-20230130160641-2xl.png 1600w"></figure><h3 id="mcetoc_1go1kdqqcj8">Event Propagation</h3><pre class="hljs" style="color: #a9b7c6; background: #282b2e; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-comment" style="color: grey;">// Registering a click event handler on the body and a button</span>
<span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string" style="color: #6a8759;">'body'</span>).addEventListener(<span class="hljs-string" style="color: #6a8759;">'click'</span>, <span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">function</span>(<span class="hljs-params">e</span>)</span>{
<span class="hljs-built_in">console</span>.log(<span class="hljs-string" style="color: #6a8759;">"Handler on body (bubbling)"</span>);
});
<span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string" style="color: #6a8759;">'button'</span>).addEventListener(<span class="hljs-string" style="color: #6a8759;">'click'</span>, <span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">function</span>(<span class="hljs-params">e</span>)</span>{
<span class="hljs-built_in">console</span>.log(<span class="hljs-string" style="color: #6a8759;">"Handler on button (bubbling)"</span>);
});
<span class="hljs-comment" style="color: grey;">// Clicking on the button results in the following output:</span>
<span class="hljs-comment" style="color: grey;">// -> Handler on button (bubbling)</span>
<span class="hljs-comment" style="color: grey;">// -> Handler on body (bubbling)</span>
<span class="hljs-comment" style="color: grey;">// Register an event handler in the capturing phase</span>
<span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string" style="color: #6a8759;">'body'</span>).addEventListener(<span class="hljs-string" style="color: #6a8759;">'click'</span>, <span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">function</span>(<span class="hljs-params">e</span>)</span>{
<span class="hljs-built_in">console</span>.log(<span class="hljs-string" style="color: #6a8759;">"Handler on body (capturing)"</span>);
}, <span class="hljs-literal" style="color: #6897bb;">true</span>);
<span class="hljs-comment" style="color: grey;">// Clicking now on the button results in the following output:</span>
<span class="hljs-comment" style="color: grey;">// -> Handler on body (capturing)</span>
<span class="hljs-comment" style="color: grey;">// -> Handler on button (bubbling)</span>
<span class="hljs-comment" style="color: grey;">// -> Handler on body (bubbling)</span></pre><pre class="hljs" style="color: #a9b7c6; background: #282b2e; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-comment" style="color: grey;">// The propagation of an event can be stopped by an event handler</span>
<span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string" style="color: #6a8759;">'button'</span>).addEventListener(<span class="hljs-string" style="color: #6a8759;">'click'</span>, <span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">function</span>(<span class="hljs-params">e</span>)</span>{
<span class="hljs-built_in">console</span>.log(<span class="hljs-string" style="color: #6a8759;">"Handler on button (bubbling)"</span>);
e.stopPropagation();
});
<span class="hljs-comment" style="color: grey;">// Clicking on the button results in the following ouput:</span>
<span class="hljs-comment" style="color: grey;">// -> Handler on body (capturing)</span>
<span class="hljs-comment" style="color: grey;">// -> Handler on button (bubbling)</span></pre><figure class="post__image"><img loading="lazy" src="https://www.finecloud.ch/media/posts/77/Pasted-image-20230130160742.png" alt="" width="481" height="216" sizes="100vw" srcset="https://www.finecloud.ch/media/posts/77/responsive/Pasted-image-20230130160742-xs.png 300w, https://www.finecloud.ch/media/posts/77/responsive/Pasted-image-20230130160742-sm.png 480w, https://www.finecloud.ch/media/posts/77/responsive/Pasted-image-20230130160742-md.png 768w, https://www.finecloud.ch/media/posts/77/responsive/Pasted-image-20230130160742-lg.png 1024w, https://www.finecloud.ch/media/posts/77/responsive/Pasted-image-20230130160742-xl.png 1360w, https://www.finecloud.ch/media/posts/77/responsive/Pasted-image-20230130160742-2xl.png 1600w"></figure><h3 id="mcetoc_1go1kdqqcj9">Default action</h3><ul><li>Some events have associated default actions:<ul><li>clicking on a link loads the link target</li><li>clicking on a submit button submits the form</li><li>pressing the down arrow scrolls the page down</li></ul></li><li>Event handlers are called before the default behaviour takes place</li><li>If the default action is unwanted, then the event handler can call preventDefault on the event object</li></ul><pre class="hljs" style="color: #a9b7c6; background: #282b2e; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-comment" style="color: grey;">// The default action can be prevented by a handler</span>
<span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string" style="color: #6a8759;">'a'</span>).addEventListener(<span class="hljs-string" style="color: #6a8759;">'click'</span>, <span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">function</span>(<span class="hljs-params">e</span>) </span>{
e.preventDefault();
alert(<span class="hljs-string" style="color: #6a8759;">"Sorry, but we don't want you to leave!"</span>);
});</pre><h2 id="mcetoc_1go387fbq1bm">AJAX</h2><ul><li>AJAX (Asynchronous JavaScript and XML) is used to create faster and more interactive web applications</li><li>AJAX enables JavaScript to load data from the server without reloading the page</li><li>On the protocol level, AJAX requests are just a normal HTTP requests</li><li>The XMLHttpRequest (XHR) object is the interface for AJAX requests</li><li>Despite the term XML in AJAX and XHR, any type of data can be loaded from the server</li><li>ES6 introduced the new Promise based Fetch API</li></ul><figure class="post__image"><img loading="lazy" src="https://www.finecloud.ch/media/posts/77/Screenshot-2023-01-31-at-07.17.30.png" alt="" width="1494" height="834" sizes="100vw" srcset="https://www.finecloud.ch/media/posts/77/responsive/Screenshot-2023-01-31-at-07.17.30-xs.png 300w, https://www.finecloud.ch/media/posts/77/responsive/Screenshot-2023-01-31-at-07.17.30-sm.png 480w, https://www.finecloud.ch/media/posts/77/responsive/Screenshot-2023-01-31-at-07.17.30-md.png 768w, https://www.finecloud.ch/media/posts/77/responsive/Screenshot-2023-01-31-at-07.17.30-lg.png 1024w, https://www.finecloud.ch/media/posts/77/responsive/Screenshot-2023-01-31-at-07.17.30-xl.png 1360w, https://www.finecloud.ch/media/posts/77/responsive/Screenshot-2023-01-31-at-07.17.30-2xl.png 1600w"></figure><pre class="hljs" style="color: #a9b7c6; background: #282b2e; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-comment" style="color: grey;">// Create a new XMLHttpRequest object</span>
<span class="hljs-keyword" style="color: #cc7832;">const</span> xhr = <span class="hljs-keyword" style="color: #cc7832;">new</span> XMLHttpRequest();
<span class="hljs-comment" style="color: grey;">// Specify the type of request: method and url</span>
xhr.open(<span class="hljs-string" style="color: #6a8759;">'GET'</span>, <span class="hljs-string" style="color: #6a8759;">'/ajax/time'</span>);
<span class="hljs-comment" style="color: grey;">// Register a callback to be notified about state changes</span>
xhr.onreadystatechange = <span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">function</span>() </span>{
<span class="hljs-comment" style="color: grey;">// Check ready state: 4 means request completed</span>
<span class="hljs-keyword" style="color: #cc7832;">if</span> (<span class="hljs-keyword" style="color: #cc7832;">this</span>.readyState === <span class="hljs-number" style="color: #6897bb;">4</span>) {
<span class="hljs-comment" style="color: grey;">// Check HTTP status: 200 OK</span>
<span class="hljs-keyword" style="color: #cc7832;">if</span> (<span class="hljs-keyword" style="color: #cc7832;">this</span>.status === <span class="hljs-number" style="color: #6897bb;">200</span>) {
<span class="hljs-comment" style="color: grey;">// Update DOM with the response text</span>
<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string" style="color: #6a8759;">'time'</span>).innerHTML = <span class="hljs-keyword" style="color: #cc7832;">this</span>.responseText;
} <span class="hljs-keyword" style="color: #cc7832;">else</span> {
<span class="hljs-comment" style="color: grey;">// Error handling...</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-string" style="color: #6a8759;">"Something failed!"</span>);
}
}
};
<span class="hljs-comment" style="color: grey;">// Send the request</span>
xhr.send();
</pre><h3 id="mcetoc_1go387fbq1bn">AJAX and JSON</h3><ul><li>The property responseText of the XMLHttpRequest object contains the HTTP response body as a string</li><li>If the response is an XML document, the data can be accessed directly by the responseXML property</li><li>If the response is a JSON document, the JSON string must be parsed manually</li></ul><pre class="hljs" style="color: #a9b7c6; background: #282b2e; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-comment" style="color: grey;">// Retrieving a JSON document</span>
<span class="hljs-keyword" style="color: #cc7832;">const</span> xhr = <span class="hljs-keyword" style="color: #cc7832;">new</span> XMLHttpRequest();
xhr.open(<span class="hljs-string" style="color: #6a8759;">'GET'</span>, <span class="hljs-string" style="color: #6a8759;">'/ajax/data.json'</span>);
xhr.onloadend = <span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">function</span>() </span>{
<span class="hljs-keyword" style="color: #cc7832;">if</span> (<span class="hljs-keyword" style="color: #cc7832;">this</span>.status === <span class="hljs-number" style="color: #6897bb;">200</span>) {
<span class="hljs-comment" style="color: grey;">// Parse the responseText into an object</span>
<span class="hljs-keyword" style="color: #cc7832;">const</span> obj = <span class="hljs-built_in">JSON</span>.parse(<span class="hljs-keyword" style="color: #cc7832;">this</span>.responseText);
<span class="hljs-built_in">console</span>.log(obj.name+<span class="hljs-string" style="color: #6a8759;">" is "</span>+obj.age+<span class="hljs-string" style="color: #6a8759;">" years old."</span>);
} <span class="hljs-keyword" style="color: #cc7832;">else</span> {
<span class="hljs-built_in">console</span>.log(<span class="hljs-string" style="color: #6a8759;">"Error..."</span>);
}
};
xhr.send();
</pre><h3 id="mcetoc_1go387fbq1bo">Same-Origin Policy</h3><ul><li>The same-origin policy is a browser security feature that restricts how documents and scripts from one origin can interact with resources from another origin</li><li>Two URLs have the same origin if the protocol, host, and port are the same</li><li>Generally, embedding a cross-origin resource using tags such as img, link, and script is permitted</li><li>Accessing a cross-origin resource using an AJAX request is blocked by default</li><li>Using CORS headers, a web server can explicitly allow certain hosts to access its resources</li></ul><h2 id="mcetoc_1go387fbq1bp">jQuery</h2><blockquote><p>”jQuery is a fast, small, and feature-rich JavaScript library” / <span style="color: var(--text-primary-color); font-family: var(--editor-font-family); font-size: inherit; font-weight: var(--font-weight-normal);">jquery.com</span></p></blockquote><ul><li>jQuery simplifies<ul><li>element selection</li><li>DOM traversal/manipulation</li><li>event handling</li><li>animation</li><li>AJAX requests</li></ul></li><li>Provides an easy-to-use API</li><li>Is tested on all major browsers</li><li>Was initially released in 2006 and used by 80% of the top 100k websites in 2022 (builtwith.com)</li></ul><h3 id="mcetoc_1go387fbq1bq">jQuery usage</h3><p>jQuery can be downloaded and included by a single script tag:<br><code><script src="js/jquery.js"></script></code><br>jQuery can also be loaded directly from jQuery or a CDN:<br><code><script src="https://code.jquery.com/jquery-3.3.1.min.js"></script></code><br><code><script src="https://unpkg.com/jquery"></script></code></p><p>Example:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-comment" style="color: grey;">// On document ready...</span>
$(<span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">function</span>() </span>{
<span class="hljs-comment" style="color: grey;">// Set the css property color of each div to red</span>
$(<span class="hljs-string" style="color: #6a8759;">'div'</span>).css(<span class="hljs-string" style="color: #6a8759;">'color'</span>, <span class="hljs-string" style="color: #6a8759;">'red'</span>);
<span class="hljs-comment" style="color: grey;">// Load some content for each selected element</span>
$(<span class="hljs-string" style="color: #6a8759;">'.content'</span>).each(<span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">function</span>()</span>{
$(<span class="hljs-keyword" style="color: #cc7832;">this</span>).load(<span class="hljs-string" style="color: #6a8759;">'/ajax/content'</span>, {id: <span class="hljs-keyword" style="color: #cc7832;">this</span>.id});
});
<span class="hljs-comment" style="color: grey;">// Register a click event handler. On each click a paragraph is added</span>
<span class="hljs-comment" style="color: grey;">// to the article element</span>
$(<span class="hljs-string" style="color: #6a8759;">'#add-content'</span>).click(<span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">function</span>() </span>{
$(<span class="hljs-string" style="color: #6a8759;">'article'</span>).append($(<span class="hljs-string" style="color: #6a8759;">"<p>More content...</p>"</span>));
});
<span class="hljs-comment" style="color: grey;">// Make an AJAX request and insert the received HTML into the DOM</span>
$.get(<span class="hljs-string" style="color: #6a8759;">'/ajax/test.html'</span>, <span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">function</span>(<span class="hljs-params">data</span>) </span>{
$(<span class="hljs-string" style="color: #6a8759;">'#result'</span>).html(data);
});
});
</pre><p>There is no magic!</p><ul><li>$ is an alias for jQuery, which is a function and thus an object</li><li>$(...) is equal to jQuery(...) and is just a function call</li><li>$.abc() calls the jQuery’s static utility function abc</li></ul><pre class="hljs" style="color: #a9b7c6; background: #282b2e; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-comment" style="color: grey;">// From jQuery’s source code: jQuery is a function and $ an alias</span>
<span class="hljs-keyword" style="color: #cc7832;">var</span> jQuery = <span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">function</span>(<span class="hljs-params">slector, context</span>) </span>{
<span class="hljs-comment" style="color: grey;">// ...</span>
};
<span class="hljs-built_in">window</span>.jQuery = <span class="hljs-built_in">window</span>.$ = jQuery;</pre><h3 id="mcetoc_1go387fbq1br">The jQuery Object</h3><ul><li>A jQuery object references one or more DOM nodes</li><li>jQuery objects have methods to manipulate and to access these nodes</li><li>Manipulations are applied to each DOM node referenced by the object</li><li>jQuery object methods are chainable</li></ul><p><code>$('div')</code><br><code>.css('background-color', '#f00')</code><br><code>.addClass('whatever')</code><br><code>.click(function(){ console.log("Clicked!"); })</code><br><code>.first()</code><br><code>.fadeOut(400);</code></p><h3 id="mcetoc_1go387fbq1bs">jQuery and AJAX</h3><ul><li>jQuery has great support for AJAX</li><li>Supported data types are XML, HTML, Script, JSON, JSONP, and TEXT</li><li>Besides the basic $.ajax() function, there are a number of convenient shorthand functions:<ul><li>$.get()</li><li>$.post()</li><li>$.getJSON()</li><li>.load()</li></ul></li><li>Provides simplified callback handling (success/error)</li><li>In addition, the jqXHR object implements the Promise interface</li></ul><pre class="hljs" style="color: #a9b7c6; background: #282b2e; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-comment" style="color: grey;">// AJAX example with success and error callback</span>
$.ajax({
url: <span class="hljs-string" style="color: #6a8759;">"/ajax/time"</span>,
type: <span class="hljs-string" style="color: #6a8759;">"GET"</span>,
dataType: <span class="hljs-string" style="color: #6a8759;">"text"</span>,
success: <span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">function</span>(<span class="hljs-params">data</span>)</span>{ $(<span class="hljs-string" style="color: #6a8759;">"#time"</span>).html(data); },
error: <span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">function</span>(<span class="hljs-params">jqXHR, status, msg</span>)</span>{ $(<span class="hljs-string" style="color: #6a8759;">"#error"</span>).html(<span class="hljs-string" style="color: #6a8759;">"Error! "</span>+msg); }
});
<span class="hljs-comment" style="color: grey;">// GET example with success callback</span>
$.get(<span class="hljs-string" style="color: #6a8759;">"/ajax/time"</span>, <span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">function</span>(<span class="hljs-params">data</span>)</span>{ $(<span class="hljs-string" style="color: #6a8759;">"#time"</span>).html(data); });
<span class="hljs-comment" style="color: grey;">// Load example</span>
$(<span class="hljs-string" style="color: #6a8759;">"#time"</span>).load(<span class="hljs-string" style="color: #6a8759;">"/ajax/time"</span>);
<span class="hljs-comment" style="color: grey;">// POST example with success callback and JSON response</span>
$.post(
<span class="hljs-string" style="color: #6a8759;">"/ajax/get_person_data"</span>,
$(<span class="hljs-string" style="color: #6a8759;">'#form'</span>).serialize(), <span class="hljs-comment" style="color: grey;">// request data</span>
<span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">function</span>(<span class="hljs-params">person</span>) </span>{ $(<span class="hljs-string" style="color: #6a8759;">'#person'</span>).html(person.name+<span class="hljs-string" style="color: #6a8759;">" is "</span>+person.age); },
<span class="hljs-string" style="color: #6a8759;">"json"</span>);
</pre><p> </p><p> </p><p> </p><p> </p><p> </p><p> </p><p> </p></div><footer class="wrapper post__footer"><p class="post__last-updated">This article was updated on März 29, 2023</p><ul class="post__tag"><li><a href="https://www.finecloud.ch/tags/javascript/">javascript</a></li><li><a href="https://www.finecloud.ch/tags/softwareentwicklung/">software development</a></li></ul><div class="post__share"></div></footer></article><nav class="post__nav"><div class="post__nav-inner"><div class="post__nav-prev"><svg width="1.041em" height="0.416em" aria-hidden="true"><use xlink:href="https://www.finecloud.ch/assets/svg/svg-map.svg#arrow-prev"/></svg> <a href="https://www.finecloud.ch/javascript-objects.html" class="post__nav-link" rel="prev"><span>Previous</span> JavaScript objects</a></div><div class="post__nav-next"><a href="https://www.finecloud.ch/javascript-advanced-features.html" class="post__nav-link" rel="next"><span>Next</span> JavaScript advanced features </a><svg width="1.041em" height="0.416em" aria-hidden="true"><use xlink:href="https://www.finecloud.ch/assets/svg/svg-map.svg#arrow-next"/></svg></div></div></nav><div class="post__related related"><div class="wrapper"><h2 class="h5 related__title">You should also read:</h2><article class="related__item"><div class="feed__meta"><time datetime="2023-01-31T07:15" class="feed__date">Januar 31, 2023</time></div><h3 class="h1"><a href="https://www.finecloud.ch/javascript-advanced-features.html">JavaScript advanced features</a></h3></article><article class="related__item"><div class="feed__meta"><time datetime="2023-01-17T20:13" class="feed__date">Januar 17, 2023</time></div><h3 class="h1"><a href="https://www.finecloud.ch/javascript-objects.html">JavaScript objects</a></h3></article><article class="related__item"><div class="feed__meta"><time datetime="2023-01-17T19:48" class="feed__date">Januar 17, 2023</time></div><h3 class="h1"><a href="https://www.finecloud.ch/javascript-arrays.html">JavaScript arrays</a></h3></article></div></div></main><footer class="footer"><div class="footer__copyright"><p>Powered by Publii</p></div><button onclick="backToTopFunction()" id="backToTop" class="footer__bttop" aria-label="Back to top" title="Back to top"><svg><use xlink:href="https://www.finecloud.ch/assets/svg/svg-map.svg#toparrow"/></svg></button></footer></div><script>window.publiiThemeMenuConfig = {
mobileMenuMode: 'sidebar',
animationSpeed: 300,
submenuWidth: 'auto',
doubleClickTime: 500,
mobileMenuExpandableSubmenus: true,
relatedContainerForOverlayMenuSelector: '.top',
};</script><script defer="defer" src="https://www.finecloud.ch/assets/js/scripts.min.js?v=6ca8b60e6534a3888de1205e82df8528"></script><script>var images = document.querySelectorAll('img[loading]');
for (var i = 0; i < images.length; i++) {
if (images[i].complete) {
images[i].classList.add('is-loaded');
} else {
images[i].addEventListener('load', function () {
this.classList.add('is-loaded');
}, false);
}
}</script><script defer="defer" src="https://www.finecloud.ch/media/plugins/syntaxHighlighter/prism.js"></script></body></html>