Using alerts and prompts is really fun, but javascript is way more powerful than just alerts and prompts! Most every site that you encounter uses a lot of javascript, and that javascript is used to manipulate the DOM.
DOM stands for "Document Object Model", which is more or less just a super fancy name for a bunch of javascript variables and methods that interact with our HTML and CSS. By using this javascript & html/css bridge, we can easily interact with the HTML by using javascript, which lets us change colors, text sizes, validate forms, etc.
The web browser (e.g. Firefox, Chrome, etc.) turns every html tag into a javascript object! Let's take a very basic website:
12<html>3 <head>4 <title> I am a website </title>5 </head>6 <body>7 <p>8 Hello World9 </p>10 <div>11 Isn't web programming really cool? 12 </div>13 </body>14</html>
What happens behind the scenes is that our browsers actually create a "model" of our site's elements. Each HTML element gets modelled as a javascript object, and each element inside of our elements has a smaller object! So, if we start at doctype html (our document) and inside of that object we have a head and a body. Inside of the head we have a title, and inside of our body we have a paragraph element and a div element. Each of those in turn have text inside them!

Now, looking at diagrams is fun, but let's see an actual document. Let's look at how the html above works. Click here, and then open your developer console (in chrome it's under developer, in firefox it's under window). In your console, type: console.dir(document).
console.dir() is a way for us to click through javascript objects in our developer console. Now, the document we see here is really big! That's because there's a lot going on behind the scenes other than just a few elements.
In your document click on body. We can see that body has a lot of elements inside of it. If you click then on childNodes you can see the children of <body>:
xxxxxxxxxx61childNodes: NodeList (5)20 #text " "31 <p> Hello World </p>42 #text " "53 <div> Isn't web programming really cool? </div>64 #text " "
This is the document object model in a nutshell! This is what lets us access parts of our web page with javascript!
Let's explore just a little more. Let's take our earlier example, and look at what nested elements look like:
xxxxxxxxxx1712<html>3 <head>4 <title> I am a website </title>5 </head>6 <body>7 <p>8 Hello World9 </p>10 <div>11 <p>12 You could go visit google if you want by clicking below!13 </p>14 <a href='www.google.com'> Go to google! </a>15 </div>16 </body>17</html>Now let's take a look. If you go to the console and write console.dir(document), then open up body and click on childNodes, you'll see that one of our children ALSO has child nodes!
xxxxxxxxxx91childNodes: NodeList (5)20 #text " "31 <p> Hello World </p>42 #text " "53 <div>6<p> You could go visit google if you want by clicking below! </p>7<a href="www.google.com"> Go to google! </a>8</div>94 #text " "
There's a lot to the DOM that we'll not cover (and you'll probably never cover - there's so much to the DOM)! It's ok not to know everything. That's what google is for!
So now that we know about what the DOM is and how it works (or at least have a general understanding of a little bit), let's look at how to work with it!
Let's take a look back at our original (very complex) page. Open the page and go to your developer console. In your console type:
xxxxxxxxxx11var myLink = document.querySelector('a');Now, type myLink in your console. What does it return? You should see:
xxxxxxxxxx11<a href="www.google.com"> Go to google! </a>What we can then do, is use the DOM to manipulate what's being displayed! Try typing:
xxxxxxxxxx11myLink.style.fontSize = '500%'Your link should've gotten a whole lot bigger!
That's not all either! We can use functions to manipulate our doms as well! Go back to our page, and this time, in your console, type:
x1// just to set our link back to its original2myLink.style.fontSize = '100%' 3var size = 1045setInterval( function() {6 myLink.style.fontSize = size + 'px'7 size = size + 18}, 50)You might want to refresh your page (or else the link will just keep growing)!
That function we used for setInterval may just look like fun and games, but what that shows us is that we can tie javascript functions directly to our DOM, which means, we can tie buttons (and so much more!) to our DOM!
There are a lot of DOM selectors. You can ultimately select anything in the document by looking at what's inside of the document (you can view with console.dir(document)). Try that again on our basic web page above.
Now if you go to your console and type:
xxxxxxxxxx11var myURL = document.URLYou'll find that myURL has a URL inside of it! Everything we'll be working with lives inside the document! We'll use document.SOMETHING for everything!
We've already looked at document.querySelector(), but there are some other document methods we'll dive into as well:
document.getElementById(): for when you want to get one specific element.document.getElementsByClassName(): for when you want to get all elements of a particular class.document.getElementsByTagName(): for when you want to get all elements of a certain tag (e.g. all <p> elements, or all <h3> elements). document.querySelector(): for when you want to search by a css style'd query and grab the very first element. document.querySelectorAll(): for when you want to search by a css style'd query and grab all the elements in the DOM.
getElementById is pretty self explanatory. It grabs a specific element by its ID. If you recall, back when we were coding our sites and learning CSS, we saw that you could technically style a webpage using multiple of the same IDs. An ID is supposed to be a unique thing. Let's see why:
xxxxxxxxxx3412<html>3 <head>4 <title> I am a website </title>5 <style>6 #greyDiv {7 background-color: lightgrey;8 }910 .coolClass {11 font-size: 2em;12 font-weight:bold;13 }14 </style>15 </head>16 <body>17 <p class='coolClass'>18 Hello World19 </p>20 <div id='greyDiv'>21 <p>22 You could go visit google if you want by clicking below!23 </p>24 <a href='www.google.com'> Go to google! </a>25 </div>26 <p class='coolClass'>27 I'm just a boring paragraph.28 </p>29 <div id='greyDiv'>30 I like to steal IDs!31 </div>3233 </body>34</html>
See how both <div> elements have the id "greyDiv"? Styling wise, our browser allows for multiple of the same IDs. Now, let's try selecting our IDs with document.getElementById(). Open the browser's console and type:
xxxxxxxxxx11var myDiv = document.getElementById('greyDiv')Because IDs are supposed to be unique, the document's function getElementById() only grabs the element with the first ID it recognizes. Notice, though, that it not only grabs the <div> but also everything inside of it. That's because the elements inside of the <div> are child nodes of the <div> itself. So when we select a specific DOM element, we're not only grabbing the element itself, we're also grabbing all of its child elements!
Reminder: When you type myDiv into the console, notice how it gives you a bunch of HTML. Type console.dir(myDiv) to see the object itself.
Suppose that you didn't want to only grab a specific element, but wanted every single element using a specific class (say you wanted to change some class styling), you can grab elements by their class names!
Go into our page, and type:
xxxxxxxxxx11var classElements = document.getElementsByClassName('coolClass')Up to now, we've only seen individual elements returned (with some nested elements inside). Now, we actually return an "HTML Collection" which is a fancy way of saying that classElements is kind of like an array of html elements that use coolClass as a class.
Sometimes you need to change specific types of elements on your page (say you want to change your list elements from all bullets to circles, because why not?), then you'd use getElementsByTagName(). Take a look at our boring list below:
xxxxxxxxxx1712<html>3 <head>4 <title> I am a website </title>5 </head>6 <body>7 <div>8 I am a boring site.9 </div>10 <ul>11 <li>Boring List</li>12 <li>Boring List 2 </li>13 <li>Boring List 3 </li>14 <li>Boring List 4 </li>15 </ul>16 </body>17</html>What if we wanted to spice our list up? Remember when we turned our list bullets into cats? Let's do that, but with javascript:
First, select all of the list items <li>s:
xxxxxxxxxx11var myList = document.getElementsByTagName('li')Now, let's take our cat style and store it in a variable!
xxxxxxxxxx51myStyle = `background-image: url('https://media.giphy.com/media/V0YMxvqOXOkEw/giphy.gif'); background-repeat: no-repeat;2 list-style-type: none;3 padding-left:75px;4 padding-bottom:50px;5`Note: Above we used the tick ` (to the left of the 1) to lets us create multi-line strings!.
Now that we have a special style, let's create a loop in the console to loop over all of our list elements and add our new style!
xxxxxxxxxx31for(var i = 0; i < myList.length; i++) {2 myList[i].style = myStyle3}BAM! Now we've made our list significantly better with cats.
Query selector is a method that basically does what we've done above, but ignores whether or not we're looking for an ID or a given class or a tag. Query selector returns the first element that matches what query it's given. So let's take our site from earlier with all of the ids and classes:
xxxxxxxxxx3412<html>3 <head>4 <title> I am a website </title>5 <style>6 #greyDiv {7 background-color: lightgrey;8 }910 .coolClass {11 font-size: 2em;12 font-weight:bold;13 }14 </style>15 </head>16 <body>17 <p class='coolClass'>18 Hello World19 </p>20 <div id='greyDiv'>21 <p>22 You could go visit google if you want by clicking below!23 </p>24 <a href='www.google.com'> Go to google! </a>25 </div>26 <p class='coolClass'>27 I'm just a boring paragraph.28 </p>29 <div id='greyDiv'>30 I like to steal IDs!31 </div>3233 </body>34</html>
Query selector uses the same types of notation as CSS, so if you want to select an id (such as greyDiv), you'd have to use the css syntax: #greyDiv, and similarly, if you wanted to select a class, you'd have ot use the syntax .coolClass.
Now to select an ID with query selector we can write:
xxxxxxxxxx11var firstClass = document.querySelector('.coolClass')Did you notice that the only element inside of firstClass is:
xxxxxxxxxx31<p class="coolClass">2 Hello World3</p>This is because query selector only selects the first item it comes across.
As a quick note, when you change the style of a selected ID or a class, you're not changing the ID or the Class styling itself, you're only changing the elements that you've selected.
Try writing:
xxxxxxxxxx11firstClass.style = 'background-color:red'If you look inside firstClass again, now it is:
xxxxxxxxxx31<p class="coolClass" style="background-color: red;">2 Hello World3</p>It still is inheriting its colors from from coolClass, but the styling on the element itself is what changed.
Our Query selector only selects a single item, but if we want to get all items of a specific type, we can use document.querySelectorAll(). This grabs not just the first item, but all items that match the query! Let's try what we did above, again!
On the page above, go to your console, and type:
xxxxxxxxxx11var allClasses = document.querySelectorAll('.coolClass')This will select not just the first class like above, but all the elements that use coolClass:
xxxxxxxxxx31NodeList (2) = $120 <p class="coolClass"> Hello World </p>31 <p class="coolClass"> I'm just a boring paragraph. </p>Now, just like above if we write a quick for loop:
xxxxxxxxxx31for(var i = 0; i < allClasses.length; i++ ){2 allClasses[i].style = 'background-color:red'3}Now we've turned all of our cool classes red!
We've already worked with a number of styling methods, however, we've only really accessed the styling in a specific way, like above where we wrote:
xxxxxxxxxx11allClasses[i].style = 'background-color:red'Our initial choice of styling in the previous examples was entirely for familiarity. We could just as easily have written:
xxxxxxxxxx11allClasses[i].style.background = 'red'The DOM lets us access styles with the javascript dot operator. While we may go back and forth in our styling, it's good to note that you can access not only the 'style' attribute, but also specific types of stylings based entirely off of the DOM's dot operators!
So far we've only worried about colration with our styling. Any styling that we've done with CSS, we can also do here:
xxxxxxxxxx1712<html>3 <head>4 <title> I am a website </title>5 </head>6 <body>7 <div>8 I am a boring site.9 </div>10 <ul>11 <li>Boring List</li>12 <li>Boring List 2 </li>13 <li>Boring List 3 </li>14 <li>Boring List 4 </li>15 </ul>16 </body>17</html>Let's wrap our list in a border. First we need to select the list:
xxxxxxxxxx11var myList = document.querySelector('ul')Now let's add a border:
xxxxxxxxxx11myList.style.border = '1px solid blue'
So far we've styled entirely by adding single styles to a given class, ID, or element, but what if we wanted to give multiple styles? We could do what we did before an add one giant string of styles to our elements. That can be time consuming.
Above, when we changed our background bullets to cats, we used this simple for loop with a style string:
xxxxxxxxxx81myStyle = `background-image: url('https://media.giphy.com/media/V0YMxvqOXOkEw/giphy.gif'); background-repeat: no-repeat;2 list-style-type: none;3 padding-left:75px;4 padding-bottom:50px;5`6for(var i = 0; i < myList.length; i++) {7 myList[i].style = myStyle8}Without the for loop that whole style sting and loop would look like:
xxxxxxxxxx201myList[0].style.backgroundImage = "url('https://media.giphy.com/media/V0YMxvqOXOkEw/giphy.gif')"2myList[0].style.backgroundRepeat = 'no-repeat'3myList[0].style.listStyleType = 'none'4myList[0].style.paddingLeft = '75px'5myList[0].style.paddingBottom = '50px'6myList[1].style.backgroundImage = "url('https://media.giphy.com/media/V0YMxvqOXOkEw/giphy.gif')"7myList[1].style.backgroundRepeat = 'no-repeat'8myList[1].style.listStyleType = 'none'9myList[1].style.paddingLeft = '75px'10myList[1].style.paddingBottom = '50px'11myList[2].style.backgroundImage = "url('https://media.giphy.com/media/V0YMxvqOXOkEw/giphy.gif')"12myList[2].style.backgroundRepeat = 'no-repeat'13myList[2].style.listStyleType = 'none'14myList[2].style.paddingLeft = '75px'15myList[2].style.paddingBottom = '50px'16myList[3].style.backgroundImage = "url('https://media.giphy.com/media/V0YMxvqOXOkEw/giphy.gif')"17myList[3].style.backgroundRepeat = 'no-repeat'18myList[3].style.listStyleType = 'none'19myList[3].style.paddingLeft = '75px'20myList[3].style.paddingBottom = '50px'
While both options work, we don't have to waste our time with either option! They're both significantly more time consuming than createing a brand new class.
Let's assume we already had a cat-class defined in our code:
xxxxxxxxxx51.cat-class {background-image: url('https://media.giphy.com/media/V0YMxvqOXOkEw/giphy.gif'); background-repeat: no-repeat;2 list-style-type: none;3 padding-left:75px;4 padding-bottom:50px;5}Now, when we want to change our bullet points, we no longer have to do all of this extra work! All we need to do is add a class to our elements:
xxxxxxxxxx11 myList.classList.add('cat-class')Now when we go to update our styles we can just:
xxxxxxxxxx31for(var i = 0; i < myList.length; i++) {2 myList[i].classList.add('cat-class')3}Problem solved!
Take the list items on our "boring list" site, and select items and try updating them. You can update by color, font (size, family, etc.), opacity, style, etc. The goal of this is to get used to using the DOM to manipulate our sites!
What makes websites reactive is that there are special things called events. Each event is something that happens on the website like a mouse moving over a portion of your site or clicking on a button! A site reacts to these events by using event handlers.
Event handlers are javascript functions that you can attach to specific elements that handle specific user interactions! Let's take a look at a basic list from our very first lecture:
HTML:
xxxxxxxxxx1 2<html>3 <head>4 </head>5 <body>6 <h1> Welcome to my site! </h1> 7 <hr />8 <ul type='square'> 9 <li>I really like to write code</li>10 <li>Does that make me a square?</li>11 <li>Some people do call me a block head...</li>12 <li>Maybe they're just not seeing me at the right ANGLE?</li>13 </ul> 14 </body>15</html>
Now let's add some CSS to our site:
x
1 .done {2 text-decoration: line-through;3 opacity: 0.5;4 }56 .selected {7 color: green;8 }
Notice how nothing happened! That's because we haven't implemented any of our css classes! We don't want to hard code our classes into our site! We want to attach them to the DOM's event listeners!
What we'll want to do is grab every single list item <li> and then attach an event listener to each. Let's grab an event:
xxxxxxxxxx11var lis = document.querySelectorAll("li")Now we've selected all of our <li>s. We'll want to add an event listener to each. But what event listeners? We want to have a mouseover, a mouseout, and a click. Let's try adding those event listeners to each <li> with a for loop:
x
1for(var i = 0; i < lis.length; i++){2 lis[i].addEventListener("mouseover", function(){3 this.classList.add("selected");4 });56 lis[i].addEventListener("mouseout", function(){7 this.classList.remove("selected");8 });910 lis[i].addEventListener("click", function(){11 this.classList.toggle("done");12 });13}14Now, let's see what those all look like together!
You may wonder why we should bother using event handlers if they're just going to put lines through list items, change colors of pages, change font sizes, but using event handlers can be an incredibly powerful tool! Let's spend the rest of today talking about making a game!
xxxxxxxxxx3112<html>3<head>4 <title>Color Game</title>5 6<body>7<h1>8 The Great 9 <br>10 <span id="colorDisplay">RGB</span> 11 <br>12 Color Game13</h1>1415<div id="stripe">16 <button id="reset">New Colors</button>17 <span id="message"></span>18 <button class="mode">Easy</button>19 <button class="mode selected">Hard</button>20</div>2122 <div id="container">23 <div class="square"></div>24 <div class="square"></div>25 <div class="square"></div>26 <div class="square"></div>27 <div class="square"></div>28 <div class="square"></div>29 </div>30</body>31</html>
CSS:
xxxxxxxxxx751body {2 background-color: #232323;3 margin: 0;4 font-family: "Montserrat", "Avenir";5}67.square {8 width: 30%;9 background: purple;10 padding-bottom: 30%;11 float: left;12 margin: 1.66%;13 border-radius: 15%;14 transition: background 0.6s;15 transition: background 0.6s;16 transition: background 0.6s;17}1819#container {20 margin: 20px auto;21 max-width: 600px;22}2324h1 {25 text-align: center;26 line-height: 1.1;27 font-weight: normal;28 color: white;29 background: steelblue;30 margin: 0;31 text-transform: uppercase;32 padding: 20px 0;33}3435#colorDisplay {36 font-size: 200%;37}3839#message {40 display: inline-block;41 width: 20%;42}4344#stripe {45 background: white;46 height: 30px;47 text-align: center;48 color: black;49}5051.selected {52 color: white;53 background: steelblue;54}5556button {57 border: none;58 background: none;59 text-transform: uppercase;60 height: 100%;61 font-weight: 700;62 color: steelblue;63 letter-spacing: 1px;64 font-size: inherit;65 transition: all 0.3s;66 transition: all 0.3s;67 transition: all 0.3s;68 outline: none;69}7071button:hover {72 color: white;73 background: steelblue;74}75
Javascript:
xxxxxxxxxx1131var numSquares = 6;2var colors = [];3var pickedColor;4var squares = document.querySelectorAll(".square");5var colorDisplay = document.getElementById("colorDisplay");6var messageDisplay = document.querySelector("#message");7var h1 = document.querySelector("h1");8var resetButton = document.querySelector("#reset");9var modeButtons = document.querySelectorAll(".mode");101112init();1314function init(){15 setupModeButtons();16 setupSquares();17 reset();18}1920function setupModeButtons(){21 for(var i = 0; i < modeButtons.length; i++){22 modeButtons[i].addEventListener("click", function(){23 modeButtons[0].classList.remove("selected");24 modeButtons[1].classList.remove("selected");25 this.classList.add("selected");26 this.textContent === "Easy" ? numSquares = 3: numSquares = 6;27 reset();28 });29 }30}3132function setupSquares(){33 for(var i = 0; i < squares.length; i++){34 //add click listeners to squares35 squares[i].addEventListener("click", function(){36 //grab color of clicked square37 var clickedColor = this.style.background;38 //compare color to pickedColor39 if(clickedColor === pickedColor){40 messageDisplay.textContent = "Correct!";41 resetButton.textContent = "Play Again?"42 changeColors(clickedColor);43 h1.style.background = clickedColor;44 } else {45 this.style.background = "#232323";46 messageDisplay.textContent = "Try Again"47 }48 });49 }50}515253function reset(){54 colors = generateRandomColors(numSquares);55 //pick a new random color from array56 pickedColor = pickColor();57 //change colorDisplay to match picked Color58 colorDisplay.textContent = pickedColor;59 resetButton.textContent = "New Colors"60 messageDisplay.textContent = "";61 //change colors of squares62 for(var i = 0; i < squares.length; i++){63 if(colors[i]){64 squares[i].style.display = "block"65 squares[i].style.background = colors[i];66 } else {67 squares[i].style.display = "none";68 }69 }70 h1.style.background = "steelblue";71}7273resetButton.addEventListener("click", function(){74 reset();75})7677function changeColors(color){78 //loop through all squares79 for(var i = 0; i < squares.length; i++){80 //change each color to match given color81 squares[i].style.background = color;82 }83}8485function pickColor(){86 var random = Math.floor(Math.random() * colors.length);87 return colors[random];88}8990function generateRandomColors(num){91 //make an array92 var arr = []93 //repeat num times94 for(var i = 0; i < num; i++){95 //get random color and push into arr96 arr.push(randomColor())97 }98 //return that array99 return arr;100}101102function randomColor(){103 //pick a "red" from 0 - 255104 var r = Math.floor(Math.random() * 256);105 //pick a "green" from 0 -255106 var g = Math.floor(Math.random() * 256);107 //pick a "blue" from 0 -255108 var b = Math.floor(Math.random() * 256);109 return "rgb(" + r + ", " + g + ", " + b + ")";110}