Saltar al contenido principal
Practical JavaScript Programming
Session 4
Wilson Su
2
https://www.slideshare.net/sweekson/
3
Wilson Su
Front-end Developer, HIE
● 6 years in web design
● Specialize in JavaScript /
CSS / HTML / OOP / Git
● Familiar with PHP / Design
Pattern
● Interested in UI & Ix Design
wilson_su@trend.com.tw
Outline
4
Practical JavaScript Programming
Chapter 7.
● What Is the DOM?
● DOM Manipulation
● Performance Optimization
HTML DOM
Chapter 8.
DOM Events
● Callback Function
● On-event Handlers
● Event Listener Registration
● Event Capturing and Bubbling
● Event Delegation
Chapter 7.
HTML DOM
5
What Is the DOM?
6
Document Object Model
7
The Document Object Model is an application programming interface that
treats an HTML or XML document as a tree structure wherein each node is
an object representing a part of the document. – Wiki
What Is the DOM?
The HTML DOM Defines
– the HTML elements as objects
– the properties of all HTML elements
– the methods to access all HTML elements
– the events for all HTML elements
8
What Is the DOM?
A Common HTML Page Structure
9
1. <!DOCTYPE html>
2. <html>
3. <head>
4. <meta charset="UTF-8">
5. <title>Aloha</title>
6. </head>
7. <body>
8. <header><h1>Aloha</h1></header>
9. <nav></nav>
10. <main></main>
11. <footer></footer>
12. </body>
13. </html>
10
html
HTML DOM Tree
What Is the DOM?
head body
metatitle header
#document
nav main footer
Root element
h1
#text
HTML DOM Node Types
11
What Is the DOM?
body
a img
#text
href src #comment
#document
html
9 Document
1 Element
2 Attribute
3 Text
8 Comment
Node VS Element
12
What Is the DOM?
Node
Element
A node is the generic name for any type of
object in the DOM.
Ex. document node, text node, comment
node, attribute node, etc.
An element is one specific type of node.
Ex. body element, div element, table
element, input element, etc.
DOM VS BOM
13
What Is the DOM?
● Document Object Model
● Manipulate the HTML document
● Standard specifications
recommended by the W3C
● Browser Object Model
● Access and manipulate the
browser window
● No standards! Each browser has
its own implementation
DOM BOM
Browser Object Model
14
What Is the DOM?
window
navigator screen historylocation
DOM Manipulation
15
Nodes
16
DOM Manipulation
<div id="profile" class="panel" data-user="Leo">content</div>
Tag ID Class
Attribute Attribute Value
Text
<!-- comments -->
Element
Comment
The id must be unique. There
can be only one element in the
document with the given id.
17
Methods for Creating Nodes
18
1. document.createElement(tag);
2. document.createTextNode(text);
3. document.createComment(comment);
4. document.createAttribute(name);
5. document.createDocumentFragment();
Creating Nodes
19
1. var elem = document.createElement('div');
2. var attr = document.createAttribute('class');
3. var text = document.createTextNode('Aloha');
4. var comment = document.createComment('comment');
5. var fragment = document.createDocumentFragment();
6.
7. console.log(elem); // <div></div>
8. console.log(attr); // class=""
9. console.log(text); // 'Aloha'
10. console.log(comment); // <!--comment-->
11. console.log(fragment); // #document-fragment
Methods for Finding Elements
20
1. document.getElementById(id);
2. document.getElementsByTagName(tag);
3. document.getElementsByName(name);
4. document.getElementsByClassName(className);
5.
6. /* HTML5 */
7. document.querySelector(selector);
8. document.querySelectorAll(selector);
Finding Elements
21
1. <form id="login">
2. <input name="account" type="text"/>
3. <input class="invalid" type="password"/>
4. </form>
5. <script>
6. var login = document.getElementById('login');
7. var inputs = document.getElementsByTagName('input');
8. var accounts = document.getElementsByName('account');
9. var invalid = document.getElementsByClassName('invalid');
10. console.log(login); // [object HTMLFormElement] { … }
11. console.log(inputs.length); // 2
12. console.log(accounts.length); // 1
13. console.log(invalid.length); // 1
14. </script>
CSS Selectors
22
DOM Manipulation
tag
#id
.class
[attribute]
> children
body div button
#header #nav #list
.icon
…
…
button[disabled]
nav > li
.panel .tab
[data-type=""]
…
table > thead > tr
…
…
⋮
Finding Elements Using Selectors
23
1. <div id="detail">
2. <span class="total">5</span> <span data-type="E">ABC</span>
3. </div>
4. <script>
5. var detail = document.querySelector('#detail');
6. var spans = detail.querySelectorAll('span');
7. var total = detail.querySelector('.total');
8. var type = detail.querySelector('[data-type="E"]');
9. console.log(detail); // [object HTMLDivElement] { … }
10. console.log(spans.length); // 2
11. console.log(spans[0] === total); // true
12. console.dir(spans[1] === type); // true
13. </script>
Element Properties and Methods for Attributes and Properties
24
1. element.id;
2. element.nodeName;
3. element.nodeType;
4. element.attributes;
5. element.dataset;
6. element.getAttribute(name);
7. element.getAttributeNode(name);
8. element.setAttribute(name, value);
9. element.setAttributeNode(node);
10. element.hasAttribute(name);
11. element.hasAttributes();
12. element.removeAttribute(name);
13. element.removeAttributeNode(node);
Element Data Attributes
25
1. <div id="user"
2. data-id="12345"
3. data-first-name="Tim">
4. </div>
Element Attributes And element.dataset
26
1. var user = document.querySelector('#user');
2.
3. user.nodeName; // 'DIV'
4. user.dataset.id; // '12345'
5. user.dataset.firstName; // 'Tim'
6.
7. user.getAttribute('data-id'); // '12345'
8. user.getAttributeNode('data-first-name').value; // 'Tim'
9.
10. user.dataset.lastName = 'Lee';
11. user.getAttribute('data-last-name'); // 'Lee'
12. user.setAttribute('data-phone', '0987654321');
13. user.dataset.phone; // '0987654321'
Element Properties and Methods for Traversing
27
1. element.firstChild;
2. element.lastChild;
3. element.childNodes;
4. element.children;
5. element.nextSibling;
6. element.previousSibling;
7. element.parentNode;
8. element.getElementsByClassName(name);
9. element.getElementsByTagName(tag);
10. element.querySelector(selector);
11. element.querySelectorAll(selector);
Node Relationships
28
DOM Manipulation
ul
li li
p
body
previousSibling
nextSibling
firstChild lastChild
span
parentNode
children
#comment
* childNodes
Element Properties and Methods for Handling Child Nodes and Content
29
1. element.innerHTML;
2. element.outerHTML;
3. element.textContent;
4. element.appendChild(node);
5. element.insertBefore(node, ref);
6. element.insertAdjacentHTML(position, html);
7. element.insertAdjacentText(position, text);
8. element.cloneNode(deep);
9. element.hasChildNodes();
10. element.removeChild(child);
11. element.replaceChild(newchild, oldchild);
Getting / Setting Element Content
30
DOM Manipulation
<div id="intro"><p>JavaScript is adynamic language.</p></div>
intro.outerHTML
intro.innerHTML
intro.textContent
var intro = document.getElementById('intro');
Getting / Setting Element Content
31
1. <p id="main"><b>Hi</b></p>
2. <script>
3. var main = document.getElementById('main');
4. console.log(main.outerHTML); // '<p id="main"><b>Hi</b></p>'
5. console.log(main.innerHTML); // '<b>Hi</b>'
6. console.log(main.textContent); // 'Hi'
7.
8. main.innerHTML = '<span>Hello</span>';
9.
10. console.log(main.innerHTML); // '<span>Hello</span>'
11. console.log(main.textContent); // 'Hello'
12. </script>
Inserting A Node
32
DOM Manipulation
Sed posuere consectetur
est at lobortis.
1. before
2. prepend
3. append
4. after
target.parentNode.insertBefore(elem, target);
target.insertBefore(elem, target.firstChild);
target.appendChild(elem);
target.parentNode.insertBefore(elem, target.nextSibling);
target
Inserting HTML
33
DOM Manipulation
Sed posuere consectetur
est at lobortis.
1. before
2. prepend
3. append
4. after
target.insertAdjacentHTML('beforebegin', html);
target.insertAdjacentHTML('afterbegin', html);
target.insertAdjacentHTML('beforeend', html);
target.insertAdjacentHTML('afterend', html);
target
Removing Nodes
34
1. /* Remove Target */
2. target.parentNode.removeChild(target);
3.
4. /* Remove A Child Node */
5. target.removeChild(child);
6.
7. /* Remove All Child Nodes */
8. while (target.lastChild) {
9. target.removeChild(target.lastChild);
10. }
Element Properties for Styles and Layouts
35
1. element.classList;
2. element.className;
3. element.style;
4. element.scrollLeft;
5. element.scrollTop;
6. element.scrollWidth;
7. element.scrollHeight;
8. element.clientHeight;
9. element.clientWidth;
10. element.offsetHeight;
11. element.offsetWidth;
12. element.offsetLeft;
13. element.offsetTop;
Getting Element Styles
36
1. <style> button { font-size: 16px; } </style>
2. <button id="btn" style="color: #222;">Refresh</button>
3. <script>
4. var btn = document.getElementById('btn');
5. var style = window.getComputedStyle(btn);
6.
7. console.log(btn.style.color); // 'rgb(34, 34, 34)'
8. console.log(btn.style.fontSize); // ''
9. console.log(style.color); // 'rgb(34, 34, 34)'
10. console.log(style.fontSize); // '16px'
11. </script>
Modifying Element CSS Classes
37
1. <button id="submit" class="btn">Submit</button>
2. <script>
3. var submit = document.getElementById('submit');
4. console.log(submit.className); // 'btn'
5. console.log(submit.classList.value); // 'btn'
6.
7. submit.className += ' btn-small';
8. submit.classList.add('btn-active');
9.
10. console.log(submit.className); // 'btn btn-small btn-active'
11. console.log(submit.classList.contains('btn-small')); // true
12. </script>
Food truck fixie locavore,
accusamus mcsweeney's marfa
nulla single-origin coffee squid.
Exercitation +1 labore velit, blog
sartorial PBR leggings next level
wes anderson artisan four loko
farm-to-table craft beer twee. Qui
photo booth letterpress, commodo
enim craft beer mlkshk aliquip
jean shorts ullamco ad vinyl cillum
PBR. Homo nostrud organic,
assumenda labore aesthetic magna
delectus mollit. Keytar helvetica
VHS salvia yr, vero magna velit
sapiente labore stumptown.
What is offsetHeight, clientHeight, scrollHeight?
38
DOM Manipulation
Offset
Height
Client
Height
Scroll
Height
border scrollbar
Performance Optimization
39
Store pointer references to
in-browser objects.
40
Finding Elements in a Bad Way
41
1. ['Add', 'Update', 'Remove'].forEach(function (action) {
2. var toolbar = document.getElementById('toolbar');
3. var button = document.createElement('button');
4. var text = document.createTextNode(action);
5.
6. button.appendChild(text);
7. toolbar.appendChild(button);
8. });
Finding Elements in a Good Way
42
1. var toolbar = document.getElementById('toolbar');
2.
3. ['Add', 'Update', 'Remove'].forEach(function (action) {
4. var button = document.createElement('button');
5. var text = document.createTextNode(action);
6.
7. button.appendChild(text);
8. toolbar.appendChild(button);
9. });
Avoid appending elements
to DOM in a loop.
43
Appending Child Nodes in a Bad Way
44
1. var list = document.getElementById('list');
2.
3. ['Iris', 'Frank', 'Sofia'].forEach(function (user) {
4. var item = document.createElement('li');
5. var text = document.createTextNode(user);
6.
7. item.appendChild(text);
8. list.appendChild(item);
9. });
Appending Child Nodes in a Good Way
45
1. var list = document.getElementById('list');
2. var fragment = document.createDocumentFragment();
3. var item, text;
4.
5. ['Iris', 'Frank', 'Sofia'].forEach(function (user) {
6. item = document.createElement('li');
7. text = document.createTextNode(user);
8. item.appendChild(text);
9. fragment.appendChild(item);
10. });
11.
12. list.appendChild(fragment);
Batch your DOM changes,
especially when updating styles.
46
Update Element Styles in a Bad Way
47
1. var box = document.getElementById('box');
2.
3. box.style.background = 'white';
4. box.style.border = '1px solid blue';
5. box.style.color = 'red';
Update Element Styles in a Good Way
48
1. var box = document.getElementById('box');
2.
3. box.style.cssText = ''.concat(
4. 'background: white;',
5. 'border: 1px solid blue;',
6. 'color: red;'
7. );
Update Element Styles in a Better Way
49
1. <style>
2. .box-highlight {
3. background: white;
4. border: 1px solid blue;
5. color: red;
6. }
7. </style>
8. <script>
9. var box = document.getElementById('box');
10. box.classList.add('box-highlight');
11. </script>
Be aware of cross-browser
compatibility.
50
Can I Use
https://caniuse.com
51
TAKE A BREAK
Chapter 8.
DOM Events
53
HTML DOM Events
● Every HTML element contains a set of events
● HTML allows event handler attributes, with JavaScript code
● Developers can use event handlers to detect and react to events
54
DOM Events
Examples Of DOM Events
● A web page has finished loading
● A browser window has resized
● A media is playing
● A text input field was changed
● A button was clicked
55
DOM Events
Callback Function
56
What is a Callback Function?
57
A callback function is a function passed into another function as an
argument, which is then invoked inside the outer function to complete
some kind of routine or action. – MDN
Callback Function
Synchronous Callback Function
1. function callback () {
2. return 'What’s up?';
3. }
4.
5. function execute (fn) {
6. return fn();
7. }
8.
9. console.log(execute(callback)); // 'What’s up?'
58
Asynchronous Callback Function
59
1. function echo (value) {
2. return value;
3. }
4.
5. console.log(echo(1));
6. setTimeout(function () { console.log(echo(2)); }, 2000);
7. console.log(echo(3));
8. // 1
9. // 3
10. // 2 (after 2 seconds)
Advanced Asynchronous Callback Function
60
1. function Alarm (options) {
2. this.name = options.name || 'Default';
3. this.callback = options.callback || (() => {});
4. this.delay = options.delay || 3000;
5. }
6. Alarm.prototype.start = function () {
7. setTimeout(() => this.callback.call(this), this.delay);
8. };
9. function callback () { console.log(this.name); }
10. new Alarm({ name: 'Alarm#1', callback }).start();
11. new Alarm({ name: 'Alarm#2', callback, delay: 1000 }).start();
12. // 'Alarm#2' (after 1 second)
13. // 'Alarm#1' (after 3 seconds)
On-event Handlers
61
Common Events
62
On-event Handlers
Window Form Mouse Keyboard
onload
onbeforeunload
onresize
onhashchange
⋮
onfocus
onblur
onchange
onselect
onsubmit
onreset
⋮
onclick
ondblclick
onmousedown
onmouseup
onmousemove
onmouseover
onmouseout
onmousewheel
⋮
onkeydown
onkeypress
onkeyup
⋮
Using Inline On-event Handlers
1. <button type="button" onclick="alert('Saved!')">Save</button>
2. <input type="text" onchange="alert('Changed!')"/>
3. <form onsubmit="alert('Submitted!')">
4. <button type="submit">Submit</button>
5. </form>
6. <div onmousemove="alert('Mouse moved!')"></div>
63
Using Inline On-event Handlers with a Callback
1. <button type="button" onclick="onSave(event)">Save</button>
2. <script>
3. /* onSave() is declared in global scope */
4. function onSave (e) {
5. console.log(e.type); // 'click'
6. console.log(e.target.id); // 'save'
7. console.log(this); // Window { … }
8. }
9. </script>
64
Registering On-event Handlers
65
1. <button id="save" type="button">Save</button>
2. <script>
3. var save = document.getElementById('save');
4.
5. save.onclick = function (e) {
6. console.log(e.type); // 'click'
7. console.log(e.target.id); // 'save'
8. console.log(this); // [object HTMLButtonElement] { … }
9. console.log(this === save); // true
10. console.log(this === e.target); // true
11. };
12. </script>
Each DOM object can have
only one on-event handler
for a given event.
66
Event Listener Registration
67
Registering / Unregistering Event Listeners
68
1. window.addEventListener(event, fn, capture);
2. window.removeEventListener(event, fn, capture);
3. document.addEventListener(event, fn, capture);
4. document.removeEventListener(event, fn, capture);
5. element.addEventListener(event, fn, capture);
6. element.removeEventListener(event, fn, capture);
Registering Event Listeners
69
1. <button id="create" type="button">Create</button>
2. <script>
3. var create = document.getElementById('create');
4. create.addEventListener('click', function (e) {
5. console.log(e.type); // 'click'
6. console.log(e.target === create); // true
7. console.log(this === create); // true
8. });
9. </script>
You cannot find elements
before the DOM is ready.
70
DOMContentLoaded Event VS load Event
71
The DOMContentLoaded event is fired when the initial HTML document
has been completely loaded and parsed. A very different event load
should be used only to detect a fully-loaded page, which means it has
finished loading all files, including subframes and images.
Event Listener Registration
Finding Elements Before DOM is Ready
1. <head>
2. <script>
3. console.log(document.getElementById('main')); // null
4. </script>
5. </head>
6. <body>
7. <div id="main"></div>
8. </body>
72
Finding Elements After DOM is Ready
73
1. <body>
2. <div id="main"></div>
3. <script>
4. console.log(document.getElementById('main'));
5. // [object HTMLDivElement]
6. </script>
7. </body>
Finding Elements After DOM is Ready
74
1. <head>
2. <script>
3. var event = 'DOMContentLoaded';
4. document.addEventListener(event, function () {
5. console.log(document.getElementById('main'));
6. // [object HTMLDivElement]
7. });
8. </script>
9. </head>
10. <body>
11. <div id="main"></div>
12. </body>
RENDER PROCESS
NETWORK
When Your Code Will Run
75
Event Listener Registration
Page Load
DOMContentLoaded
Event
load
Event
Get
JS
Get
CSS
Build
DOM
Get
HTML
Run
JS
Build
CSSOM
BlockedIdle
Request
Page
Render
Code waiting for the DOMContentLoaded event
Code waiting for the load event
1
2
3
4
5
6 7 8
Event Capturing and Bubbling
76
Capturing And Bubbling
77
Event Capturing and Bubbling
html
#document
body
button
window
Capturing Phase
(1)
Target Phase
(2)
Bubbling Phase
(3)
Event starts here
Target
Event Capturing and Bubbling - Snippet 1/2
78
1. <button id="button" type="button">Add</button>
2. <script>
3. function onClick (e) {
4. console.log(e.eventPhase, e.currentTarget.name);
5. }
6.
7. function registerClickEvent (target) {
8. target.addEventListener('click', onClick, true);
9. target.addEventListener('click', onClick);
10. }
11. </script>
Event Capturing and Bubbling - Snippet 2/2
79
1. <script>
2. var button = document.getElementById('button');
3.
4. window.name = 'Win';
5. document.name = 'Doc';
6. button.name = 'Btn';
7.
8. registerClickEvent(window);
9. registerClickEvent(document);
10. registerClickEvent(button);
11. /* When the button is clicked */
12. // 1 'Win', 1 'Doc', 2 'Btn', 2 'Btn', 3 'Doc', 3 'Win'
13. </script>
Prevents the Event from Bubbling up the DOM Tree
80
1. var save = document.querySelector('#save');
2.
3. document.body.addEventListener('click', function (e) {
4. /* This event handler won’t be executed. */
5. });
6.
7. save.addEventListener('click', function (e) {
8. e.stopPropagation();
9. });
Keeps the Rest of the Handlers from Being Executed
81
1. var save = document.querySelector('#save');
2.
3. document.body.addEventListener('click', function (e) {
4. /* This event handler won’t be executed. */
5. });
6.
7. save.addEventListener('click', function (e) {
8. e.stopImmediatePropagation();
9. });
10.
11. save.addEventListener('click', function (e) {
12. /* This event handler won’t be executed either. */
13. });
Canceling the Default Action of Elements
82
1. <input id="checkbox" type="checkbox"/>
2. <a id="link" href="https://google.com">Google</a>
3. <script>
4. function preventDefault (e) {
5. e.preventDefault();
6. }
7. var checkbox = document.querySelector('#checkbox');
8. var link = document.querySelector('#link');
9.
10. checkbox.addEventListener('click', preventDefault);
11. link.addEventListener('click', preventDefault);
12. </script>
Event Delegation
83
Registering Event Listeners in a Bad Way
84
1. var list = document.getElementById('list');
2. var items = list.querySelectorAll('li');
3. var length = items.length, i = 0;
4.
5. while (i < length) {
6. items[i].addEventListener('click', function (e) {
7. e.target.style.color = 'red';
8. });
9. ++i;
10. }
Attaching a Delegated Event Handler to a Parent Element
85
1. function delegator (elem) {
2. return function (type, selector, fn) {
3. var listener = function (e) {
4. e.target.matches(selector) && fn.call(e.target, e);
5. };
6. elem.addEventListener(type, listener);
7. return listener;
8. };
9. }
10. var list = document.getElementById('list');
11. delegator(list)('click', 'li', function (e) { … });
12. delegator(list)('click', 'li.active', function (e) { … });
Pay special attention
event handlers that
fire in quick succession.
(e.g. resize, mousemove)
86
Optimized Resize Event Handler
87
1. function throttler (fn) {
2. var timer;
3. return function (e) {
4. if (timer) { return; }
5. timer = setTimeout(function () {
6. timer = null;
7. fn.call(e.target, e);
8. }, 66); // 15fps
9. };
10. }
11. function handler (e) { console.log('Resized!'); }
12. window.addEventListener('resize', throttler(handler));
You do not really understand
something unless you can
explain it to your grandmother.
- Albert Einstein
88
Questions?
89
Reference
90
● Callback (computer programming) - Wikipedia
● Document Object Model - Wikipedia
● Handling Events :: Eloquent JavaScript
● JavaScript and HTML DOM Reference - W3Schools
● JavaScript Events
● Running Your Code at the Right Time | KIRUPA
● Web API reference - Web technology reference | MDN
● Web performance potimization
Practical JavaScript Programming
THANKS