Lect03 JavaScript 2
Lect03 JavaScript 2
Lecture 3
JavaScript (2)
DOM Manipulation & JS Timers
Today’s Contents
"use strict";
// your code
Writing "use strict"; at the very top of your JS file turns on strict syntax
checking:
● Shows an error if you try to assign to an undeclared variable
● Stops you from overwriting key JS system libraries
● Forbids some unsafe or error-prone language features
You should always turn on strict mode for your code!
The “module pattern”
(function() {
// statements;
})();
Wraps all of your file's code in an anonymous function that is declared and
immediately called.
You can only access HTML elements after the “load” event has fired
"use strict";
(function() {
window.addEventListener("load", init);
// no access to the document here
function init() {
// we now have access to the DOM tree!
// set up your initial document event handlers here.
}
})();
DOM Manipulation: Classes
What if I want to change the styles of an element on the page?
Hiding/Showing Elements
.hidden {
display: none;
}
id("my-img").style.display = "none";
toggle(classname) Removes a class that is in the list, adds a class that is not
in the list.
replace(oldclass, newclass) Replaces the old class with the new class.
Example: adding a class to classList
Add the hidden class to the element when you want to hide it:
id("my-img").classList.add("hidden");
Remove the class to restore the element’s styles to the state before:
id("my-img").classList.remove("hidden");
id("my-img").classList.toggle("hidden");
More about event ● Multiple event handlers
● Removing event handlers
handling ● Event objects
addEventListener with multiple events
removeEventListener
As opposed to adding event listeners to an element, you can also remove them:
Event Objects!
Recall that the event handler function can be attached to objects (window,
DOM elements, etc.)
source.addEventListener("click", responseFunction);
function responseFunction(e) {
// we can access the click Event object here!
}
When the event occurs, an Event object is created and passed to the
event listener. You can "catch" this event object as an optional first
parameter to get more information about the event.
DOM Manipulation: Nodes
What if I want to add or remove elements on my page?
<body> Visualization of a DOM Tree
<header> <main>
Hello
<ol> <p>
World
dolor sit
<html> <span>
<html> amet ...
<li> ...
Lorem
ipsum
Creating New Elements
Name Description
When creating new DOM elements using JS, you may use
document.createElement often.
You are allowed to copy this shortcut function to your JavaScript code. Just be
sure to use comments to describe it so that you and others understand what
this function does.
function gen(tagName) {
return document.createElement(tagName);
}
Other handy alias functions
function id(id) {
return document.getElementById(id);
}
function qs(selector) {
return document.querySelector(selector);
}
function qsa(selector) {
return document.querySelectorAll(selector);
}
Adding and Moving Nodes on the DOM
When you have a parent DOM node, you can add or remove a child
DOM node using the following functions:
Name Description
let li = document.createElement("li");
li.textContent = "A list item!";
id("my-list").appendChild(li);
Removing Nodes from the DOM
When you have a parent DOM node, you can remove a child DOM node using
the following functions:
Name Description
parent.removeChild(node) Removes the given node from this node’s child list
qs("#my-list li:last-child").remove();
/* or */
let li = qs("#my-list li:last-child");
li.parentElement.removeChild(li);
Removing all Nodes using innerHTML
// before js
<section id="fyi">
<p>hi</p>
<p>bye</p>
<section> let el = document.getElementById("fyi");
el.innerHTML = "";
// after js
<section id="fyi">
</section>
DOM Traversal Methods
We can use the DOM tree to traverse parent/children/sibling relationships (e.g. to
remove an element from its parent node). Every node's DOM object has the
following (read-only) properties to access other DOM nodes in the tree:
Name Description
These are the common traversal properties we’ll see, but you can find a complete list here
DOM Tree Traversal Example
Write JS code to get these elements using DOM Tree Traversal methods:
addEventListener("click", openBox());
addEventListener("click", openBox(param));
Anonymous Functions
class Test:
def hello(self): What do these all have in common?
print(self)
Python ● They all refer to the object that owns the method.
What happens to this in JavaScript?
vs.
function draftReply(startingText) {
this.parentNode.appendNode( /*....*/ );
// ...
}
Arrow functions DO NOT bind this
We've seen how this refers to the bound element in an event handler.
However, arrow functions do not bind this the same way.
element.addEventListener("dblclick", function() {
// All good! this === element that was clicked
this.parentNode.removeChild(this);
id("result").textContent = "the element has been removed";
});
element.addEventListener("dblclick", () => {
// error! this === window
this.parentNode.removeChild(this);
id("result").textContent = "the element has been removed";
});
Comparing this in different callback functions
function init() {
id("btn1").addEventListener("click", namedFunction);
id("btn2").addEventListener("click", function() {
console.log("this === " + this); // this === #btn2
});
id("btn3").addEventListener("click", () => {
console.log("this === " + this); // this === window
});
}
function namedFunction() {
console.log("this === " + this); // this === #btn1
}
Debugging JS - ● Strategies
● JS Debugger
Tips & Tricks
Strategies
function launchRocket() {
console.log('Launching!!!');
}
Errors in your code are printed to the Chrome Dev Tools console
● Error message
● File the error originated from
● Line number
The console error messages even link you to the line in your code where the
error occurred!
Use the JS Debugger
function startCountDown() {
let count = 10;
for (let i = count; i > 0; i--) {
console.log(i + "...");
}
console.log("0!");
}
This prints a countdown to the console as soon as it's called. But what if we
want to delay each line printed by 1 second?
Setting a Timer
Function Description
function init() {
id("demo-btn").addEventListener("click", delayedMessage);
}
function delayedMessage() {
id("output-text").textContent = "Wait for it...";
setTimeout(sayHello, 3000);
}
function sayHello() {
id("output-text").textContent += "Hello!";
}
Motivating the timerId variable
● These examples will assume we are writing inside a module pattern for
brevity, but you can refer to the full examples (linked on slides).
“Toggling” animation with clearInterval
<button id="toggle-btn">Start/Stop<button>
function delayedMultiply() {
// 6 and 7 are passed to multiply when timer goes off
setTimeout(multiply, 2000, 6, 7);
}
function multiply(a, b) {
console.log(a * b);
}
Any parameters after the delay are eventually passed to the timer function
● Doesn't work in IE; must create an intermediate (anonymous) function to pass the
parameters
Why not just write this?
setTimeout(sayHello(), 2000);
setTimeout(sayHello, 2000);
function startCountDown() {
let i = 10;
setInterval(function() {
console.log(i + "...");
i--;
}, 1000);
console.log("0!");
}
When startCountDown is called, we assign a new interval to our timer and start a one
second countdown at 10.
When we reach 0, we need to clear the interval from the window's tasks
Timers Summary
● When you want to call a function after a specified delay in time, use
setTimeout.
● When you want to call a function repeatedly every X seconds, use
setInterval (though you can also use setTimeout recursively!)
● For both types of timers, if you want to stop the delay/interval you'll need a
variable to keep track of the timer id (returned by both functions) to pass to
clearTimeout/clearInterval