sandbox.html we dealt with in the third post.
As we look at the HTML, each project is made up of a
section element with an
id, which represents each specific project, and they both have the class of
So when I want to access one, specifically, I can use the
id attribute, and when I want to access these elements together as a set, I can use the
project class. Inside the project, there is a title, an image and a paragraph for each project.
If we look at the
document just in and of itself, we could see that this object represents the web page or the document running within the browser.
document.getElementById and pass in an
id value, what it returns is a reference to the
section element because it has the
Now that works great for accessing elements with a specific
id, but what if I want to select items based on their class name? Well, I can do that very easily as well. Here, I can use
document.querySelector. Now, what we pass into the
querySelector function will seem very familiar to you. It will take the same type of selectors that we used in building CSS rules. So to access my
project class, I type in
Now the querySelector function returns the first match of your selector. Here, you can see that it returned the
project-1 because that was the first item that had the
Now we can get all of them just as easily by calling
document.querySelectorAll. When we pass in
.project, what’s returned is a node list of all the matching elements.
The queries you can pass into the
querySelector function can be straightforward like I’ve shown you or even a little more complex. Retaking a look at the HTML, I have a
img element with a
src attribute that has a value of
https://via.placeholder.com/150. So we can take these same values and format them in a selector to use with
Now there is one more thing I want you to notice as well, see how I used the double quotes on the outside of the selector and the single quotes on the inside. The quotes on the inside are necessary to tell the selector that we’re searching for a string value that the
src will be equal to, but we can’t use the double quotes because that would signal to the browser that the selector was going to end early. Any time you need to use quotes inside of quotes, you can use the single quotes inside the double or use the double quotes inside the single. The important thing is you only have to be consistent.
Working with Elements
So with this Sharing is the key! link here right now, if I click on it, it’ll open up in the same browser tab as my sandbox page. And if we look at the HTML, the anchor has an
href attribute and a class attribute.
But there’s an attribute that we can add named
target that allows us to designate the destination of the link location. So let’s go down to the script on the page and add a little bit of code.
Now what I’m doing here is using
document.querySelector to select the only anchor element on the page. Once I have access to it, I can call the
setAttribute function and tell it that I want to add an attribute
target and set its value to blank. All right, well, let’s save it and switch back over to our page and see how it behaves now. Now when I click on the link, it opens up in a new tab.
setAttribute function works to create an attribute that isn’t there yet or update an attribute’s value.
So here I’ll open up the developer tools, right‑click on the link, and select Inspect. When I come into the Elements pane, it automatically creates the
$0 variable to select the element. And so I wouldn’t use
$0 when I’m coding a web page. But here, I’d like to show you how you can do it for experimentation within the browser development tools. So now I’ll switch over to Console, and I’ll verify I have a value for
So this variable is now pointing to this element. Now from there, what I can do is I can ask for the value of a specific attribute. By calling
getAttribute and passing in the name of the attribute that I want to look at, I get the value of our new target attribute.
I could also ask for the
href value. And I could also remove an attribute. Passing in the attribute name removes the attribute from the element.
Now you can see that the HTML has been updated so that the target element is not there.
So now when I click on the link, instead of this opening up in a new tab, it opens up in the same tab, all because we’ve removed that attribute.
Now there’s one attribute that acts a little bit different than the others, and that’s the class attribute. So in the next section, I’d like to show you how to work with the classList HTML attribute.
Selecting elements is the first step, but once you have access to those elements, it opens up all kinds of possibilities for you to do something with them. Here we have our page that has our projects on it, and each section has a class list with
desktop. Now, we’ll run some code that will update the classes that are applied to the project.
But first, let’s go to the CSS style sheet and add this rule for the
dark class to make things easier to understand.
I want to locate an element with the class
desktop and add
dark to the class list. When we take a look at the web page with the
dark class applied, we could see that the
project-2 is rendered with a dark background.
document.querySelector to get access to the element with the
project class. When we look at the
project variable, we can see that the first project is selected.
Now, from there, I can change the classes that are associated with this element. You might think that I could go to
dark, and in fact, we can look at that list here and see it returns both
Now, what if I want to remove it? Well, I can call
project.classList and run the
remove function. And so now, when we look at the class list, there are only
One of the elements that you’ve seen me using a lot but we haven’t discussed yet is the script element in depth. Now the script tag is the element that we use on a page to execute scripts. The location of the script tag is essential. Let’s think about how a website works. When you send a page to the browser, the code is processed from top to bottom. Remember, HTML and CSS are responsible for the structure and layout of the page, while the scripts are responsible for its behaviour. I bring all this up because it’s for these reasons we want the script tag near the bottom of the page.
- One is that the scripts are easier to write and maintain when they’re in dedicated files. You can load as many script files as you want into a page, and by splitting up the code and the logic, just makes your applications easier to work with.
- The second main reason is that browsers make copies of files that they request from the server. We call it caching. When a file is cached, the browser loads its file from a saved copy rather than making a new request to the server. Now, this speeds up the web a lot. So if you have a script file that many pages of your site use, then adding it as an external file makes a lot of sense so you can take advantage of browser caching.
There are other excellent reasons to use external scripts, but these are the two main ones that are relevant right now. So I have an external script provided for us, and just so that you can see the location, I created
sandbox.js right next to
sandbox.html and moved the code from the script tag in the
sandbox.html page into the
Now to reference it, the script tag will have a source attribute that points to
sandbox.js. And then, I need to add a type attribute and set that equal to
The Window object is the context for scripts running within a web browser, and we’ll use Sharing is the key website to illustrate.
So the window generally refers to the window that’s running inside a current tab. So if I open up the About page in a separate tab, there are two different Window objects where your script will run, even though they’re technically within the same website. They’re independent pages, so they get a different context.
The window hosts the document object, which is the DOM for this tab. So if we take a look at the
window, you can see scores of functions and properties available off the
window. And much of the functionality of the browser is available off of the
Now, from here, we have access to things like the
location of the browser tab. We can get all kinds of information about the URL of the page and even the different segments that make up this location. So we could do an entire course on the
window object inside the browser. But for now, what you need to know is that we’ll use the
window object to get access to the built‑in functionality of the browser.
If you use nothing else inside the browser developer tools, you will use the debugger. The debugger allows you to stop code from running at a specific point so you can inspect what’s happening right at that line of code.
Now, I’ve written a simple script here, and if you haven’t already noticed, I’ve introduced a bug into my code. So I’m concatenating together my first name and last name, but here, when I go to use them together, I use the variable called
firstName instead of
So, if we save the file, you’ll notice that I get a reference error, and it says
firstName is not defined. Now, this is a straightforward script. We can see the error very quickly.
But let’s imagine for a moment that this bug is hard to find. Within the browser developer tools, I can go over to the Sources tab, and when I click on the
sandbox.js file, it shows me right where I have an error for this line of code. Now, if I come down to the line numbers and I click on line 2, you’ll notice that it’s highlighted with this blue arrow. It is called a breakpoint, and you can see in the window on the right that it shows the list of breakpoints.
A breakpoint is a point at which the execution will break, or essentially stop, and allow you to examine what’s going on in the code. So now, with that breakpoint set, I can refresh the page and notice what happened. It highlighted the line, and it shows up at the top that it’s paused in the debugger.
Now, as I look around on my page, I can hover over variables, and I can see at the variable named
first has a value of
"John". The variable of
last is not yet declared because we haven’t executed this line yet.
So, I’ll click on Step over the next function call button, or you can press F10, or CTRL+apostrophe, either one of those will work, and now the next line of code has been run.
So the variable named
last now has a value of
"Smith". But you’ll notice it didn’t keep going. It stopped at the following line of code. So at this point, I can hover over
last and see that I have a value. And then I see
firstName. Well, that doesn’t have value. And so, by stopping the code as it’s executing, I have a much better chance of figuring out what my problems are.
So, here we’ve realized,
firstName is not the variable that we need. What we need is to call that
first. So now I can switch over to the editor. Make the change. Remember, the execution is still stopped on line 3, so I’ll let it run by clicking on the paused in debugger button at the top of the page and let’s refresh it, and now it hits the breakpoint again.
first has a value of
"John", step over the following line,
last has a value of
last now have values. I fixed my bug, and now the name variable has
"JohnSmith" as its final value. On the right-hand side, you’ll notice over here that it shows the current script that’s running and all the variables that are currently in scope and their values.
By setting breakpoints and using the browser’s debugging tools, you have a lot of power available to you to debug your applications. Now that we have a good view of what it takes to write and debug code let’s start writing some code against the browser and find out how to work with HTML elements on the page.
AddEventListener is the function you use to run some code when a given event takes place. The syntax for this function is made up of a few different parts. Here
addEventListener is being called off the window object. But now we need to tell the browser which event we’re interested in. The name of the event is added first between quotes here because the name is a stream. Now there are dozens of events to choose from, and in the coming examples, I’ll show you how to use a few.
The second argument of the function expects a function. It is similar to how the
forEach function worked when we spoke about arrays, where the function defined here is called when the event notification is sent.
This is an anonymous function, and it is being called gets a reference to an object that contains information about the event that was just raised. Often you’ll need to access different information to find out more about what’s happening in the program, and that will be available within the event object.
Inside the function is where you write the code that’s meant to respond to the event.
Here we are back with our sandbox page, and one of the first events that I’d like to look into is to know whether or not the page is completely loaded within the browser. This is important because our page is represented in the browser through the Document Object Model.
Now, let’s recall our discussion from cascading style sheets, where we talked about the Document Object Model, or the DOM. In that case, it’s an in‑memory hierarchical representation of the elements that make up a web page. When the browser requests a page, the server’s response includes HTML that’s read by the browser. Based on the HTML structure, elements are created in‑memory that correspond to the markup in the page.
Now load times can vary depending on many factors. Sometimes web pages load so quickly that it seems instantaneous to our eyes. Still, there’s always a certain amount of time that elapses before a web page is completely loaded and rendered inside the browser to a computer. Since there’s this delay in time, even if it’s slight, the code we write needs a way to know that, indeed, that page is loaded before attempting to run.
The event that tells us that the page is loaded and ready to work is called
DOMContentLoaded. So the first thing that we want to do is go to the
window object and call
DOMContentLoaded. Then we’ll create an anonymous function that’s called when the event fires. Within the body of this function, we can add in our logic that runs as the page loads. So we’ll log out to the console saying that the page is loaded.
When we save the page, it’s reloaded, and only until all of the page contents are loaded into memory. Each of the HTML elements are processed in the DOM. The
DOMContentLoaded event is fired. We get the console to report that the page is loaded. Our page is elementary, so it goes fast, but this is the place where you want to begin writing code if you’re going to use any elements on your HTML page.
If we wanted to interact with a button on the page, we could do that simply here within this event. I’ll start by creating a new element for a button that we can click on. I’ll assign the
button with the id of
click‑me and the text of Click Me.
So now, down at
DOMContentLoaded, I can add in the logic to interact with my element. The first thing that I want to do is select the element on the page. Here, I’ve used the
querySelector function to pass in an id selector to find that element on the page. Next, we’ll add an event listener on the button to listen for the click event. And with that, I can log out to the console that the button was clicked.
So, as I save the page and reloads, I get a button here rendered on the page. So when I click on that, I get a message logged to the console, saying, “The button was clicked.”.
And lastly, I’ll show you how to handle the event when the device orientation changes within the browser. It is an event that only fires for mobile devices, so I’ll show you how we can simulate it within the desktop browser. First, we’ll add an
orientationChange off the window object. Now we can look at the screen object to get orientation information about the device. We can get the angle and the orientation type, and we can take that information and log it out to the browser. So as I save the changes, when we look over in the console, you don’t see anything show up.
Remember that we have the mobile emulator available within the browser developer tools, and I can switch over to that. You’ll notice that as I switched over to the mobile view, it fired this event. Expanding the window out to make it a little bit easier to see, if I click on this button for Rotate, you’ll notice that as the event fires, the type goes from portrait primary to landscape primary 0 degrees to 90 degrees.
Now, there is a wide array of available events as you build your web apps, and we’ll be using a number of them as we finish up the implementation for Bethany’s Pie Shop in the next post. But next, let’s get a feel for what type of APIs are available directly within the browser.
API stands for Application Programming Interface. Now that’s just a fancy way of saying that there’s some code that you can use to work directly with the browser’s functionality. Putting it another way, using the browser’s API, you can control the features and the behaviour of a web browser. The best way to get an overall look at what APIs are available is to go over to the MDN web docs, and we’ll bring up the web API page that lists all the built‑in functionality of a web browser.
Now, by looking around on this page, you’ll be able to see that there’s a vast array of functionality that you can tap into. Want to draw something on the page?
Want to request an additional file from the server? Fetch does that.
Want to create drag‑and‑drop interaction on your page? Well, it is called HTML Drag and Drop API.
What about saving data in the database? The tragically named IndexedDB can do that for you.
And the list goes on and on. But there’s one problem. Not all of these APIs are available in all browsers. How do you know what you can use and whether or not there are alternatives if something you need isn’t available? Well, I’ll tell you right now, options do exist, and we’ll discuss those next.
Fallbacks and Polyfills
Sometimes the API you want to use isn’t fully supported by browsers, and we’ll look at how to determine browser support next. But for now, I want to introduce a few terms regarding API support. In situations where API support is inconsistent, there are two types of scripts that you can include on your pages that help compensate for the missing feature.
A fallback is a script that your browser can fall back to if the built‑in functionality doesn’t exist. The fallback often doesn’t do as much as what the native API is supposed to do, but they exist as an alternative to built‑in browser functionality.
On the other hand, a polyfill is meant to mimic built‑in browser functionality by already using supported features. The main benefit here is that a polyfill is specifically built to have the functions, objects, properties, and behaviour that work the same way the built‑in browser functionality is supposed to work.
This way, once browsers fully support the API, you should remove the polyfill, and everything should work. Now that’s the promise. But be warned, you should still do extensive testing before you make changes like that.
Now that you’re familiar with fallbacks and polyfills let’s look at a few tools that can help you determine whether an API is supported well enough for your application.
Determining browser support is crucial because you need to know that the code you write will work with the web browsers accessing your site. Now, there are a couple of tools that you can use to help make these decisions. The first one is HTML5 Please. This website lists different native APIs and gives you some hints on how well they’re supported and what to do if they’re not.
In conjunction, caniuse.com is an excellent resource that brings you a broad spectrum of statistics regarding how well APIs are supported on different browsers. You saw caniuse.com a little bit when we talked about CSS, and we’ll use it a bit more here.
So we’ll take a look at a couple of different APIs here within HTML5 Please so you can get an idea of what this website offers. First, let’s take a look at the API of local storage. This is a built‑in API that allows you to store information within a web browser. You’ll notice that HTML5 Please has marked localStorage as use. So this is a fully supported API, meaning that you can use it with high confidence in just about any web application.
As we look at the bottom, you’ll notice a link down here that says View browser share %. When we click on that, that brings us to caniuse.com directly to the section on localStorage. Here we get an idea of browser support and any extra resources that are available for this API.
Now, localStorage is an extensively well‑supported API, so let’s look at something a little different. Currently, Web Workers are marked as used but with a fallback. So the advice here is that there may be a small percentage of web browsers that don’t support the API, and it gives you some ideas of how to work around that if you need to have 100% browser capability.
All right, let’s look at IndexedDB. This API is marked as caution with a fallback. So here it gives you some recommended polyfills, IDBWrapper and the IndexedDB Polyfill.
When we go over to caniuse.com for IndexedDB, scrolling down to the Resources tab, you’ll notice that it has links for polyfills and detailed information about places where there might be some deficiencies in the implementation. But you’ll see from the chart here, almost every modern web browser supports IndexedDB.
All right, let’s look at one last example. The WebSQL API is marked as to avoid. It is a deprecated API, and you don’t want to use this API unless you have a particular reason. And the advantage here is that the website gives us all of that knowledge ahead of time without having you figure that out the hard way.
If you need any help or something is going wrong, let me know. It will be my pleasure to help you. If you want to extend some point, we have discussed, contact me so we can cover in the fllowing posts.
We also have pro bono projects just in case you are interested in learning more about them.
Be aware of why we started this project by clicking here.
Learn more about other posts here.
If you are a good reader like myself, I recommend the following readings:
- Docker for Developers: Develop and run your application with Docker containers using DevOps tools for continuous delivery
- Responsive Web Design with HTML5 and CSS: Develop future-proof responsive websites using the latest HTML5 and CSS techniques, 3rd Edition
See you in the next post!