Skip to content

Instantly share code, notes, and snippets.

@michaelcpuckett
Last active September 21, 2024 20:58
Show Gist options
  • Save michaelcpuckett/9a838e0590f98016ccd8369ff82e2fc2 to your computer and use it in GitHub Desktop.
Save michaelcpuckett/9a838e0590f98016ccd8369ff82e2fc2 to your computer and use it in GitHub Desktop.
ATTN: Code:You students

DOM APIs

What is ECMAScript?

"JavaScript" is the colloquial name for ECMAScript.

The ECMA in ECMAScript refers to ECMA, an organization in Europe and the standards body that determines what goes into the ECMAScript language (JavaScript).

ES3 / ECMAScript 3

  • ~2006
  • First attempt to get all the browser vendors on the same page and use consistent DOM APIs.
  • Old browsers, some other unique environments.

ES6 / ECMAScript 6

  • ~2015
  • Modern "JavaScript" that we're teaching today.
  • Modern browsers only (includes Edge but not Internet Explorer, for instance.)

What is "JavaScript" / ES6?

Recall the basics of JavaScript that we have already covered. They are mostly very general and abstract. They do not specifically reference the HTML elements on a web page.

  • Data types

    • String
    • Number / Float
    • Boolean
    • Array
    • Object
    • Function
      • Class
    • Map - Array-like (but always unique!)
    • Set - Object-like
    • "Weird ones" / "Offballs"
      • undefined
      • null
      • NaN
      • Infinity
  • Built-in Global objects

    • Math
      • .random()
      • .round(num)
        • .ceil(num)
        • .floor(num)
      • .max(num1, num2)
      • .min(num1, num2)
      • .abs(num)
      • .sqrt(num)
      • .pow(num, exponent)
    • Date
      • .now()
    • JSON
      • .parse()
    • Promise
      • new Promise(callbackFunction)
        • (resolve, reject)
      • promise.then()
      • promise.catch()
      • Promise.all()
  • Control flow

    • If/Else
    • Loops

What is our JavaScript environment?

So far, our JS environment is the browser.

The browser is the windowed application that runs on an operating system that happens to have a orchestrated system for rendering HTML, CSS, and JS.

The browser's scripting engine handles ES6 + the DOM API.

What is the DOM API?

  • Stands for:
    • Document Object Model
    • Application Programming Interface
  • Not part of ECMAScript 6, but gets added to our environment automatically as additional functionality by the web browser
  • Provides access to the current state of the rendered tree of HTML elements as well as other properties about the user's browser

What is window?

  • The global object
    • Every JavaScript environment has a global object, sometimes referred to as globalThis.
  • Provides access to various browser-specific functionalities including the DOM API.
  • Represents the browser at a high level, including the browser application's resizable/scrollable container.
  • Because it is the global object, the window. is implied, and does not need to typed out in code, but sometimes helps for clarity.
    • console.log("Hello world") vs
    • window.console.log("Hello world")
      • Don't use window.
      • Here console works like a built-in global object.
    • const totalHeight = innerHeight + 300 vs
    • const totalHeight = window.innerHeight + 300
      • Use window. for clarity.
      • innerHeight by itself is ambiguous, and it's easy to accidentally create a local variable called innerHeight!
    • I prefer to use the longer window.document.querySelector() over simply document.querySelector(), since it's easy to accidentally create a local variable called document!

What properties exist on window?

  • .innerWidth <-- viewport width
  • .innerHeight <-- viewport height
  • .console
    • .log()
  • .scrollY <-- window scroll position (up/down)
  • .scrollX <-- window scroll position (left/right)
  • .location <-- page's current URL
  • .history
    • .back() <-- Equivalent to user hitting "back" button
  • .navigator
  • .document <-- See below

What methods exist on window?

  • .addEventListener("scroll")
  • .addEventListener("resize")
  • .removeEventListener("eventType", callbackFunction)
  • .scrollTo(x, y)
    • Scroll the web page to a specific point
  • .alert("message")
    • Show the default pop-up dialog with OK button
  • .setTimeout(callbackFunction, interval)
    • Do something in the future
  • .requestAnimationFrame(callbackFunction)
    • Do something on next frame render
  • .fetch(url, options) => Promise
    • Retrieve an external resource
  • .matchMedia("css media query")
    • .addEventListener("change", callbackFunction)
    • Callback fires when CSS media query changes to true or false

What is window.document?

  • Represents a web page loaded in the browser
    • Web pages used to be called "documents" because the early web was primarily designed to display research papers
  • Holds the element tree

What properties exist on window.document?

  • .documentElement => Element
  • .activeElement => Element that is currently focused
  • .cookie
    • window.document.cookie = mycookie="helloworld";

What methods exist on window.document?

  • .querySelector("css selector")
  • .querySelectorAll("css selector")
  • .createElement("element-name")

How is an HTML element represented?

  • All elements in the DOM use the Element interface
  • Elements inherit the Node interface
    • Not all Nodes are Elements
    • The other kind of Node is TextNode
  • HTML elements (div, a, span, etc) get the HTMLElement interface.
    • Other types of Elements might include SVG elements, etc.
    • More specific types of HTML elements have specialized interfaces:
      • HTMLButtonElement
      • HTMLBodyElement
      • etc.
  • .querySelector() only retrieves Elements, not text nodes, but may retrieve SVG Elements or other Elements that don't use the HTMLElement interface.

What properties exist on the HTMLElement interface?

  • .textContent => The text nodes that are direct descenants of an element
  • .innerText => All the text nodes of this element and all its descendants.
  • .children => HTMLCollection
  • .parentElement => Element
  • .nextElementSibling => Element
  • .classList <-- API for manipulating element's class attribute
    • .add("className")
    • .remove("className")
    • .toggle("className")
    • .contains("className") => Boolean
  • .style <-- only mapping to the element's style attribute
    • .setProperty("color", "red")
    • .getPropertyValue("color") // red

Compare element.style to window.getComputedStyle(element) which gives you what was typed in the CSS stylesheet, and "won":

window.getComputedStyle(element);
  • window.getComputedStyle()
    • .setProperty()
    • .getPropertyValue()

What are live HTMLCollections and NodeLists?

  • Array-like representations of the DOM
  • Update as the DOM changes

const allMyBeautifulParagraphs = window.document.querySelectorAll("p");

  • Wrap in Array.from() to get a real array that won't change

const allMyBeautifulParagraphs = Array.from(window.document.querySelectorAll("p"));

What methods exist on the HTML Element interface?

  • .querySelector("css selector")
  • .querySelectorAll("css selector")
  • .closest("css selector")
  • .matches("css selector")
  • .contains(element)
  • .append(element)
  • .prepend(element)
  • .remove()
  • .getAttribute("attribute-name")
  • .setAttribute("attribute-name", "value")
  • .scrollIntoView()
  • .focus()
  • .getBoundingClientRect()
    • .height
    • .width
    • .top
    • .left
  • .addEventListener("eventType", callbackFunction)
    • "click"
    • "change"/"input"
    • "submit"
  • .removeEventListener("eventType", callbackFunction)
myButtonElement.addEventListener("click", (event) => {
  console.log(event.eventType);
});

vs.

function buttonClickHandler(event) {
  console.log(event);
}

myButtonElement.addEventListener("click", buttonClickHandler);

// Can only remove via reference to same function used to add
myButtonElement.removeEventListener("click", buttonClickHandler);

What is the event argument in an event listener callback function?

  • Provides properties and methods for the event that is being fired inside the callback function of .addEventListener()

What methods exist on the Event interface?

  • .preventDefault()
  • .stopPropagation()

What properties exist on the Event interface?

  • Other properties depend on the type of the Event
  • .currentTarget
    • The element that the event listener was added to.
myButtonElement.addEventListener("click", (event) => {
  console.log(event.currentTarget); // myButtonElement
});
  • .target
    • The element that is currently responding to the event listener callback
    • May be firing on the element that the event listener was added to, or may be firing on one of its ancestors or descendants.

What is the difference between event bubbling and capturing?

  • Some events will only fire on one element (the .currentTarget)

  • Others "bubble" meaning the callback is fired on all ancestors and descendants of the .currentTarget element

  • There are two paradigms for propagating events:

    • Bubble mode (Bottom -> Top)

      • The default mode
      • Fires on the innermost child element first
      • Then fires on every ancestor element
    • Capture mode (Top -> Bottom)

      • Specified as an extra argument in .addEventListener()
      • Fires on the top-most ancestor element first
      • Then fires on every descendant element
myButtonElement.addEventListener(
  "click",
  (event) => {
    console.log(event.currentTarget); // myButtonElement
  },
  {
    capture: true, // Set capture mode instead of bubble mode
  }
);
  • To only fire on a specific element, guard by comparing target to currentTarget:
if (event.target !== event.currentTarget)) {
  return;
}

// Logic continues if they are the same.
// ...
  • To prevent further bubbling/capturing at any point, call:
    • event.stopPropagation()

What is event delegation?

  • You could add an event listener to many elements that all exist inside the same ancestor element...
<ul class="my-list">
  <li></li>
  <li></li>
  <li></li>
</ul>
const listItemElements = Array.from(
  window.document.querySelectorAll(".my-list > li")
);

listItemElements.forEach((listItemElement) => {
  listItemElement.addEventListener("click", doTheThing);
});
  • ...Or you could add one event listener to the common ancestor element, knowing the event will bubble and its callback function will fire on all the children:
const listElement = window.document.querySelector(".my-list");

listElement.addEventListener("click", (event) => {
  if (event.target.matches(".my-list > li")) {
    doThething();
  }
});
  • This is called event delegation, and can be used for performance purposes, since setting addEventListener so many times can cause browser sluggishness, vs just setting one time.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment