Exciting Web Development Journey – Pie Shop Website 6/7

Overview

Welcome back to Sharing Is The Key. Now that you are already acquainted with JavaScript basic concepts, let’s push a little bit further and create some interactivity in the Pie Shop website.

In this post, we cover some of the building blocks you need to create interactive web apps. We’ll discuss how to write code that can respond when certain things happen in the browser, like when the page loads, when you click a button, and so on. We’ll also review a wide array of built‑in features and functionalities available to you through JavaScript as you build web apps. Finally, we cover how to determine browser support for different features and what to do if that feature isn’t yet supported.

Selecting Elements

One of the fundamental actions that you’ll use JavaScript for working with the web page is selecting elements on the page. Going back to our 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 project.

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.

Now to use JavaScript to access these elements, I can do several different ways, and one of the first is to use a function called getElementById.

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.

SITK- Pie Shop - selecting elements - document

By calling document.getElementById and pass in an id value, what it returns is a reference to the section element because it has the id of project-1.

SITK- Pie Shop - selecting elements - document.getElementById()

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 .project.

SITK- Pie Shop - selecting elements - document.querySelector()

Now the querySelector function returns the first match of your selector. Here, you can see that it returned the section for project-1 because that was the first item that had the project class.

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.

SITK- Pie Shop - selecting elements - document.querySelectorAll()

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 querySelector.

SITK- Pie Shop - selecting elements - more complex document.querySelector()

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

Now that we’re able to select elements on the page let’s see what we can do with them. One of the actions that you can take against an element is to change attributes in JavaScript.

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.

SITK- Pie Shop - working with elements - link

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.

SITK- Pie Shop - working with elements - setAttribute()

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.

SITK- Pie Shop - working with elements - setAttribute(target, _blank)

The 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 $0.

SITK- Pie Shop - working with elements - $0 variable

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.

SITK- Pie Shop - working with elements - $0.getAttribute(target)

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.

SITK- Pie Shop - working with elements - $0.removeAttribute(target)

Now you can see that the HTML has been updated so that the target element is not there.

SITK- Pie Shop - working with elements - $0.removeAttribute(target) - result

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.

classList Property

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 project and desktop. Now, we’ll run some code that will update the classes that are applied to the project.

SITK- Pie Shop - classList Property - class list values

But first, let’s go to the CSS style sheet and add this rule for the dark class to make things easier to understand.

SITK- Pie Shop - classList Property - dark rule

I want to locate an element with the class project and 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.

SITK- Pie Shop - classList Property - dark class applied to project-2

Now, what I just did was to add it directly here into the HTML. And so now I’d like to show you how to do the same thing using JavaScript. So we’re back to the web page’s default state, so I can use 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.

SITK- Pie Shop - classList Property - using querySelector

Now, from there, I can change the classes that are associated with this element. You might think that I could go to project.class and set that equal to something, but that does not work in JavaScript. The word class is a reserved word. And so here, what we’ll use is a class list. By accessing the class list, I can call the add function and pass in a class name. Here, I don’t add a dot before the name. Because this isn’t a selector, I’m passing in a name. And so now, as I press Enter, the list of classes associated with that element now includes dark, and in fact, we can look at that list here and see it returns both project, desktop and dark.

SITK- Pie Shop - classList Property - adding dark to the project class list

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 project and desktop.

SITK- Pie Shop - classList Property - removing dark from the project class list

Script Tag

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.

Often it shows up as the last element before the body’s closing tag. It ensures that our pages aren’t halted from loading and being styled due to a script that didn’t work quite right. So as you’ve seen throughout this post, I’ve added JavaScript to the script element.

There are times, probably more often than not, when you’ll want to move the script into an external file. We move JavaScript into its file for a lot of different reasons:

  • 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 sandbox.js file.

SITK- Pie Shop - script tag - moving javascript code to a dedicated file

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 text/javascript. This attribute is important because it tells the browser what language the script is coming in as. The only client‑side scripting language we use is JavaScript, but it’s added here just for completeness with modern web development. Now some tags within an HTML page are self‑closing. So if you notice, the meta tag up here doesn’t have an associated closing tag. The script tag does need the closing tag, though. Even though we don’t put anything in between the script tag, we still have to close it here explicitly. When we save the file, the page reloads, and we get the Sharing is the key! link working the same way as before.

SITK- Pie Shop - script tag - linking javascript to html

Next, let’s take a look at how the window object is used inside of the browser and through JavaScript.

Window

The Window object is the context for scripts running within a web browser, and we’ll use Sharing is the key website to illustrate.

SITK- Pie Shop - window - sitk website

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.

SITK- Pie Shop - window - sitk website - about page

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 window object.

SITK- Pie Shop - window - sitk website - window object in the about page

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.

SITK- Pie Shop - window - sitk website - window.location info

Debugging

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 first.

SITK- Pie Shop - debugging - known error

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.

SITK- Pie Shop - debugging - save and get an error

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.

SITK- Pie Shop - debugging - set a breakpoint in the source tab

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.

SITK- Pie Shop - debugging - execution stopped at the breakpoint

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.

SITK- Pie Shop - debugging - step over the next function call

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.

SITK- Pie Shop - debugging - debugging again with the code fixed

So first has a value of "John", step over the following line, last has a value of "Smith", and first and 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.

SITK- Pie Shop - debugging - checking the final result

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.

Events

Events, in programming languages, just like in real life, signal when something happens. When an event occurs in a program, the application sends a notification to the rest of the code, essentially saying, hey, something happened here. You get to select which messages you want to respond to this event. Now, for instance, there’s an event that fires when the page loads. You can also listen for an event that fires as a button is clicked. You can even tap into an event that lets you know when a change in the orientation of your mobile device has occurred. And these are just a few, among many, events that you can use in your app. In JavaScript, you set up your code to listen for events. Let’s take a look at the function that allows us to respond to these events, and that function is called addEventListener.

addEventListener Function

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.

SITK- Pie Shop - addEventListener - first argument

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.

SITK- Pie Shop - addEventListener - second argument

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.

SITK- Pie Shop - addEventListener - second argument - event object

Inside the function is where you write the code that’s meant to respond to the event.

SITK- Pie Shop - addEventListener - second argument - logic content

Okay, let’s look at some actual implementations and how you can respond to a few different events in JavaScript.

Demo: Events

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.

SITK- Pie Shop - demo events - sandbox page

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.

SITK- Pie Shop - demo events - abstract DOM representation

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 addEventListener for 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.

SITK- Pie Shop - demo events - DOMContentLoaded

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.

SITK- Pie Shop - demo events - DOMContentLoaded - result

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.

SITK- Pie Shop - demo events - creating a button element

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.

SITK- Pie Shop - demo events - adding code to the event listener function

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.”.

SITK- Pie Shop - demo events - adding code to the event listener function - result

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 eventListener for 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.

SITK- Pie Shop - demo events - adding listener to orientationchange event

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.

Native API

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.

SITK- Pie Shop - native apis - MDN web docs

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?

SITK- Pie Shop - native apis - canvas

Want to request an additional file from the server? Fetch does that.

SITK- Pie Shop - native apis - fetch

Want to create drag‑and‑drop interaction on your page? Well, it is called HTML Drag and Drop API.

SITK- Pie Shop - native apis - HTML Drag and Drop

What about saving data in the database? The tragically named IndexedDB can do that for you.

SITK- Pie Shop - native apis - IndexedDB

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.

SITK- Pie Shop - api absense - fallback

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.

SITK- Pie Shop - api absense - polyfill

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.

Browser Support

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.

SITK- Pie Shop - browser support - html5 please

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.

SITK- Pie Shop - browser support - caniuse

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.

SITK- Pie Shop - browser support - html5 please - localStorage

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.

SITK- Pie Shop - browser support - caniuse - localStorage

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.

SITK- Pie Shop - browser support - html5 please - web workers

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.

SITK- Pie Shop - browser support - html5 please - indexedDB

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.

SITK- Pie Shop - browser support - caniuse - 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.

SITK- Pie Shop - browser support - html5 please - WebSQL

Next up, we have the last post in this series where I’ll demonstrate to you how to update the rest of Bethany’s website to collect user data and send it to the server. And this is where it gets exciting because now we get to put into practice all the knowledge that you’ve learned about JavaScript to update the website to make it truly interactive.

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.

Contact us for any suggestions. And follow us on FacebookInstagram and Twitter.

If you are a good reader like myself, I recommend the following readings:

  • Docker Quick Start Guide: Learn Docker like a boss, and finally own your applications
    • 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
    • JavaScript: The Definitive Guide: Master the World’s Most-Used Programming Language 7th Edition

    See you in the next post!