Core 1 Interaction

Java-Script

JavaScript is the language/format for adding interactivity to a web page—based on actions or events from the user. Where do we even start with JS? (Everyone calls it JS.) It is so massive and often seems unapproachable. So we’ll go through a bit of background, and then look at some very practical examples you might want in your work.

Going back to our first analogy, JavaScript is the muscles of the web. Like HTML (the bones) and CSS (the skin), it is ultimately still just text that is parsed by our browsers. Like CSS, it can live within HTML documents, but is usually saved separately with the extension .js

JavaScript was first created by Brendan Eich over just 10 days in 1995, and has been through a myriad of evolutions, paths, missteps, and enhancements since then. It has nothing formally to do with Java, confusingly—other than being contemporaries and sort-of competitors (thus the name). JavaScript won the race, by every measure, and is ubiquitous on the modern web.

The idea was to make something that Web designers, people who may or may not have much programming training, could use to add a little bit of animation or a little bit of smarts to their Web forms and their Web pages.

Brendan Eich

Like HTML/CSS, JavaScript was a malleable, interpreted (not compiled) language running in the browser—meaning the source code could be seen by anyone, and anyone could borrow or modify it for their needs. And so as our computers—and thus our browsers—became faster and cheaper, JS was used for more and more things.

Libraries, Frameworks and Vanilla

You’ll often hear people talk about libraries or frameworks in the context of JavaScript—one of the ways it is malleable. These are collections of Javascript code with their own specific ideas, paradigms, and syntax, that expand upon what the language can do (or can do quickly or easily) on its own, out of the box.

Things like jQuery (old-school, now), React, Vue, Angular, D3, and p5 (to name some popular ones) are all written in and are interfaced with (controlled by) JavaScript as well. They are often created to do something JavaScript doesn’t yet support on its own (in/famously, jQuery) or with a niche use/focus (like data-visualization, with D3). There are many, many frameworks and libraries.

There is also NodeJS. That's JavaScript but on the server-side, meaning it can act as a server and can interact with folders on your computer and so on. Many frameworks like React or Vue rely on Node JS.

When you write JS without libraries, it is usually called plain or vanilla JavaScript. The language has evolved so much that we can do a lot, here, and this is where we’ll start. And while JS does many things, we’ll first just use it in the most simple way—to make our web pages more interactive.

Where does JS live?

Very much like CSS, JavaScript code can live in several places:

  1. Inline as attributes
  2. Via <script> elements within HTML documents
  3. As separate/external *.js files (the right way)

1. Inline event handlers

JS was first added directly like attributes in HTML tags, just like CSS—but attached/listening for specific events:

<button onclick="alert('The button was clicked!');">Click here!</button>

Note the single quotes when nested/inside doubles!

This works for very, very simple things, but—for many of the same reasons as inline CSS—is brittle and doesn’t scale with complexity or across multiple pages. Try writing a whole, elaborate function in there! No good.

You might see these in old examples/code, but don’t use these now! If you see them, it’s probably an indication the code is outdated.

2. Wrapped in <script> tags

So again like CSS, JavaScript can be enclosed in its own special tag, the <script> element. (These are also, somewhat confusingly, called inline scripts.) Anything inside the tag should be written in JavaScript syntax and will be executed right away, in the order/position of the tag within the HTML document.

Since this script isn’t directly on an element anymore (as above), we then have to identify the target element with querySelector, and then attach the onclick event to it:

<button id="example">Click here!</button>
<script>
	// Set up a variable for our button!
	let button = document.querySelector('#example'); // Any CSS selector.
	button.onclick = () => { // Attach the click event.
		alert('The button was clicked!'); // Pop an alert!
	};
</script>
html, body { height: 100%; }

body {
	--base: 20px;

	align-items: center;
	display: flex;
	font-family: sans-serif;
	justify-content: center;
	padding: var(--base);
}

button {
	background-color: deepskyblue;
	border-radius: calc(var(--base) / 2);
	cursor: pointer; /* Show the Mickey-Mouse hand! */
	padding: calc(var(--base) / 2);
}

Note the different // comment syntax for JS! And we had to add cursor: pointer; for the button in our CSS, to indicate it is actionable. Mind your affordances.

Here the onclick is a shorthand for using addEventListener. We also store (declare) the element here as a variable, to keep our code readable. These are a bit like their CSS counterparts. Ergonomics!

Oh also, <noscript>

Some people block/disable JavaScript—for performance or accessibility reasons, or to hide advertising/annoyances, and so on. This is less and less common these days, since so many sites completely rely on JS. It isn’t always feasible to replicate your site behavior entirely without JS, but you can use a special <noscript> tag to show content only when scripting is turned off:

You can test this by disabling JavaScript in your DevTools.

3. Separate/external *.js files

By far the most common, flexible way to include JavaScript is externally—again, like CSS. The difference here is that instead of a <link> element, we still use a (now empty) <script> tag, with the addition of a src="filename.js" attribute:

<script defer src="script.js"></script>

Same JavaScript as the example above, but now moved over into a nice, separate, JS-syntax-highlighted file. This will still run when the document gets to the <script> (and in its place/order) as before, and the defer attribute allows it to “see” the HTML (not yet loaded) below it. We can then move the script up into our <head>, along with the other external files:

// Set up a variable for our button!
let button = document.querySelector('#example');

// Attach the click event.
button.onclick = () => { 
	// Pop an alert!
	alert('The button was clicked!');
};
<button id="example">Click here!</button>
html, body { height: 100%; }

body {
	--base: 20px;

	align-items: center;
	display: flex;
	font-family: sans-serif;
	justify-content: center;
	padding: var(--base);
}

button {
	background-color: deepskyblue;
	border-radius: calc(var(--base) / 2);
	cursor: pointer; /* Show the Mickey-Mouse hand! */
	padding: calc(var(--base) / 2);
}

Stays readable/clean with long documents and lots of files. Where there is one JS file, there are often many.

Data Types

The three most common Data Types are:

  1. Numbers
  2. Strings
  3. Booleans
    ... and Undefined

Numbers

Numbers are numbers—JavaScript won’t distinguish between different types of numbers, like integers or negative numbers. It handles numerical values the same.

To type a number into the console, just enter numerals without quotes. If you enter a number into the console, you’ll get that number back.

You can also type math expressions into the console, hit enter, and you’ll get the result.

Strings

Strings are used for storing and manipulating text. A JavaScript string is zero or more characters written inside quotes.

Here are a few strings:

"Hi"
"Hello World!"
"A 'Hello, World!' program is a computer program that outputs 'Hello, World!' to a user."
""

Booleans

Booleans represents one of two values: true or false.

Try typing the following into your console and hit enter. What’s returned is a boolean value, false:

14 > 23
16 >= 16
40 < 10000
"hello world" == "Hello world"

Booleans are especially useful when you’re writing conditional statements, which you use a lot in programming. You’re often telling the computer— if this condition is true, then run this code.

Let’s say you want to use JavaScript to turn your into dark mode website during nighttime hours. The way you’d write that is something like:

var today = new Date();
var today_sunset = 18;

if (today.getHours() >= 18) {
  document.body.style.backgroundColor = "black";  
  console.log("good night");
} else {
  console.log("good day");
}

Undefined

Any variable that has not been assigned to a value is undefined.

A method or statement also returns undefined if the variable that is being evaluated does not have an assigned value. A function returns undefined if a value was not returned.

Undefined | MDN

For example:

var goodDesign =
console.log(goodDesign);

Operators

Operators allow us to work with and change our numbers. Like with simple (and complex) math.

Addition: 9 + 7
Subtraction: 12 - 79
Multiplication: 54667 * 8
Division: 12 / 6
Remainder (Modulo): 6 % 1
Exponents:  2 ** 3

Try typing a simple mathematical expression into the console. For example:

569 / 12

For more details about Arithmetic Operators.

After simple math, we can also start combining our data types. Try typing each of the following lines into your console…

9 + 7
"9" + "7"
true + true
9 * false
2018 + " Olympics"

Not all of these are going to work… One important thing to notice:

There many other kinds of operators that perform operations on other types of data, for example assignment operators or comparison operators .

Variables

Variables are where progamming gets interesting. JavaScript variables are containers for storing data. Variables let you store a piece of data and refer to it later, as it will be stored in memory.

You can name a variable whatever you want as long as there are no spaces or hyphens. The problem with hyphens is that JavaScript will think you’re trying to use subtraction. Instead, it’s common to see something called camelCase used in JavaScript.

Try to keep variable names simple. You can declare a variable with let, followed by the variable’s name.

let expert;
let today;
let age;
let alive;

Use = and a value to set the value for a variable. Using =, you’re storing a value in the variable.

let expert = "Carolyn Peck";
let today = "February 22";
let age = 57;
let alive = true;
let ageTomorrow = age + 1;

Try entering those variables into the console. To get their values back again, all you need to do is retype that variable’s name.

There are three types of variables:

Arrays

Arrays are list-like objects used to store data. Arrays allow you store more than one item in only a single variable.

Think of it like this: when writing your grocery list, you could use a separate piece of paper for each item you need to buy (a variable). However this is silly and unneeded—could you imagine how hard it would be to carry all that paper around with you? So, you use one piece of paper for all of your items. This one piece of paper is your array.

An array is written like this:

var groceries = ["eggs", "spinach", "olive oil"]

You can refer to each item in your array with an index number. Note that the first item in array is at position 0.

groceries[0] 
groceries[1] 
groceries[2] 

You can also update the values of your array. For example, what if we wanted to edit our shopping list to remember that we only need 6 eggs? You could use the index number to update that value.

groceries[0] = "6 eggs"

Like setting the value of a variable, here you’re using = to set the value of one item in the array.

To access the entire array. Just enter its name. The console will return information about the array, including its length and contents to you.

groceries

The real strength of JavaScript arrays are their incredibly useful built-in array properties and methods.

The length property sets or returns the number of elements in an array.

groceries.length

Functions

A function is a block of code that returns a result. It's one of the fundamental building blocks in JavaScript.

Think of a function like a recipe. You start with different ingredients (these could be variables, HTML elements, numbers, etc) and combine them by executing the steps. You get a dish at the end–this is called the result. By wrapping your code into functions, it’s easier to maintain and reuse functionality.

Functions consist of:

// Define a function named "someName" that takes a single parameter.
function someName(parameter) {
  // Log the value of the "parameter" to the console. This will return "undefined".
  console.log(parameter);
}

// Create a constant variable named "argument" and assign the string "foo" to it.
const argument = "This string will be our result";

// Call the "someName" function with the "argument" variable as its argument, which will log the string to the console.
someName(argument);

Examples

Adding/removing a class

Okay, time for a more practical example: probably the most common thing you will use JS for—especially as we’re starting out—is simply to add or remove (toggle) a class from something when the user interacts with your page (such as clicking on a menu).

The element needs two states in your CSS: without the class and then with the class. The JavaScript interaction/event will switch between them, and our CSS transition will smooth out the… transition.

We’ll use addEventListener and querySelector to listen for clicks, but then modify the classList of a different element:

let highlightClass = 'highlight'; // Set up variables.
let textBlock = document.querySelector('section'); // Any selector.
let switchButton = document.querySelector('#example');

switchButton.onclick = () => { // Attach the event.
	textBlock.classList.toggle(highlightClass); // Toggle the class!
};
<section>
	<p>I’ve just added some text here to have another element, and also added some CSS to style it a bit—nothing too fancy.</p>
</section>
<button id="example">Click here!</button>
section { /* Initial state, without the class. */
	background-color: gold;
	padding: calc(var(--base) / 2);
	transition: all 1s ease-in-out; /* Transition everything. */
	will-change: transform; /* Improves the aliasing! */
}

section.highlight { /* When the class is applied with JS! */
	background-color: aquamarine;
	transform: rotate(5deg);
}

html, body { height: 100%; }

body {
	--base: 20px;

	align-items: center;
	display: flex;
	flex-direction: column;
	font-family: sans-serif;
	justify-content: center;
	padding: var(--base);
	row-gap: var(--base);
}

button {
	background-color: deepskyblue;
	border-radius: calc(var(--base) / 2);
	cursor: pointer; /* Show the Mickey-Mouse hand! */
	padding: calc(var(--base) / 2);
}

The class can be toggled on any element in your HTML (or often, even just on document.body itself)! querySelector takes any CSS selector, even other classes. Also you an specifically use classList.add and classList.remove, if you don’t want the on-and-off behavior from classList.toggle.

You can do many, many things with this basic “add a class” JS!

Watching for scrolling

Another very common use for JavaScript is to do something when an element enters or exits the viewport (scrolling into or out of view)—like fading or moving something in.

Again we’ll need two states in our CSS—defined with/without a class. But now we’ll use the user’s scrolling, instead of a click, to toggle the switch.

This used to be unnecessarily hard in JavaScript, and was one of the things jQuery was created to help with. But now we can use IntersectionObserver to watch the element:

let highlightClass = 'highlight'; // Set up variables.
let highlightBlock = document.querySelector('section:nth-child(4)');

// Set up an IntersectionObserver.
let sectionObserver = new IntersectionObserver((entries) => {
	let [entry] = entries; // Don’t worry about this, for now.

	// When it is intersecting, apply the class; otherwise, remove it.
	if (entry.isIntersecting) {
		highlightBlock.classList.add(highlightClass);
	} else {
		highlightBlock.classList.remove(highlightClass);
	}
});

sectionObserver.observe(highlightBlock); // Watch for it!
<section>
	<p>I’ve just added some text here to have another element, and also added some CSS to style it a bit—nothing too fancy.</p>
</section>
<section>
	<p>I’ve just added some text here to have another element, and also added some CSS to style it a bit—nothing too fancy.</p>
</section>
<section>
	<p>I’ve just added some text here to have another element, and also added some CSS to style it a bit—nothing too fancy.</p>
</section>
<section>
	<p>I’ve just added some text here to have another element, and also added some CSS to style it a bit—nothing too fancy.</p>
</section>
<section>
	<p>I’ve just added some text here to have another element, and also added some CSS to style it a bit—nothing too fancy.</p>
</section>
<section>
	<p>I’ve just added some text here to have another element, and also added some CSS to style it a bit—nothing too fancy.</p>
</section>
<section>
	<p>I’ve just added some text here to have another element, and also added some CSS to style it a bit—nothing too fancy.</p>
</section>
section { /* Initial state, without the class. */
	background-color: gold;
	padding: calc(var(--base) / 2);
	transition: all 1s ease-in-out; /* Transition everything. */
	will-change: transform; /* Improves the aliasing! */
}

section.highlight { /* When the class is applied with JS! */
	background-color: aquamarine;
	transform: rotate(5deg);
}

body {
	--base: 20px;

	align-items: center;
	display: flex;
	flex-direction: column;
	font-family: sans-serif;
	padding: var(--base);
	row-gap: var(--base);
}

Note the if/else statement, an example of conditional logic.

You will often want to use this on multiple elements—and remember, when in code, don’t repeat yourself! So we can use querySelectorAll to select multiple elements, and then a forEach loop to run the same class for each of them:

let highlightClass = 'highlight'; // Variables again.
let highlightBlocks = document.querySelectorAll('section'); // All.

// Loop through the list, doing this `forEach` one.
highlightBlocks.forEach((block) => {
	let sectionObserver = new IntersectionObserver((entries) => {
		let [entry] = entries;

		// This is a "ternary" operator——a condensed if/else.
		entry.isIntersecting ? block.classList.add(highlightClass) : block.classList.remove(highlightClass); 
	}, {
		root: document, // This is only needed in the example iframe!
		rootMargin: '-33% 0% -33% 0%', // CSS-ish: top/right/bottom/left.
	});

	sectionObserver.observe(block); // Watch each one!
});
<section>
	<p>I’ve just added some text here to have another element, and also added some CSS to style it a bit—nothing too fancy.</p>
</section>
<section>
	<p>I’ve just added some text here to have another element, and also added some CSS to style it a bit—nothing too fancy.</p>
</section>
<section>
	<p>I’ve just added some text here to have another element, and also added some CSS to style it a bit—nothing too fancy.</p>
</section>
<section>
	<p>I’ve just added some text here to have another element, and also added some CSS to style it a bit—nothing too fancy.</p>
</section>
<section>
	<p>I’ve just added some text here to have another element, and also added some CSS to style it a bit—nothing too fancy.</p>
</section>
<section>
	<p>I’ve just added some text here to have another element, and also added some CSS to style it a bit—nothing too fancy.</p>
</section>
<section>
	<p>I’ve just added some text here to have another element, and also added some CSS to style it a bit—nothing too fancy.</p>
</section>
section { /* Initial state, without the class. */
	background-color: gold;
	padding: calc(var(--base) / 2);
	transition: all 1s ease-in-out; /* Transition everything. */
	will-change: transform; /* Improves the aliasing! */
}

section.highlight { /* When the class is applied with JS! */
	background-color: aquamarine;
	transform: rotate(5deg);
}

body {
	--base: 20px;

	align-items: center;
	display: flex;
	flex-direction: column;
	font-family: sans-serif;
	padding: var(--base);
	row-gap: var(--base);
}

Here I’ve also adjusted the rootMargin from the viewport/default, so the elements don’t transition immediately.

Some miscellaneous tips

Alright, that is a lot. Like I’ve been saying—JavaScript is a whole thing. Here are some other tips, as you start to explore:


This page was adapted from Michael Fehrenbach's An intro to JavaScript and Rosa McElheny's JS 1: Basics.