DOM

  • DOM = window.document

  • BOM = window.document, window.navigator, window.location, window.history, window.screen, etc

  • in DevTool, $0 returns the selected Element, so you can use normal DOM APIs to access: ex, $0.classList

DOM Ready

  • event DOMContentLoaded : the browser fully loaded HTML, and the DOM tree is built, but external resources like pictures <img> and stylesheets may be not yet loaded.

    • document.addEventListener("DOMContentLoaded", ready);

    • the defer scripts already loaded

    • the async scripts might NOT be loaded

  • function load: the browser loaded all resources (images, styles etc)

    • window.onload = function() {}

  • function beforeunload/unload : when the user is leaving the page

    • window.unload = function() {}

// handle the case when we add the callback after the document is already loaded 
if (document.readyState === "complete" ||
    (document.readyState !== "loading" && !document.documentElement.doScroll)
) {
  callback();
} else {
  document.addEventListener("DOMContentLoaded", callback);
}

Reference: https://javascript.info/onload-ondomcontentloaded

Script: async vs defer

DOM Manipulation

Node (like root interface) -> Document -> Element

Selector

You can use the following selector on document or element.

NOTE you cannot use pure number in your selector

  • The selector attributes should be CSS identifiers or strings. So you cannot use number there!

  • var a = document.querySelector('a[data-a="1"]');

Select the first or null ($(selector) in DevTools):

  • const myElement = document.querySelector('#foo > div.bar input[name="login"]')

  • Returns the first descendant Element using DFS + Pre-order traversal

  • It's not live, compare to getElementsByTagName()

Select all matching ($$(selector) in DevTools):

  • const myElements = document.querySelectorAll('.bar')

  • Returns NodeList

  • iterate: for .. of or forEach or .item(i)

Compare/Match:

  • node.contains(element)

  • e.target.nodeName == "LI"

  • e.target.matches('input') (Element.matches)

Traverse:

  • traverse parents: element.closest('selector')

  • how to polyfill? see MDN

Others: using above is recommended.

Attributes

Generally, you can do:

  • element.getAttribute('id') or element.getAttribute('data-parent')

  • element.setAttribute('tabindex', 3);

  • element.id

Data attributes

  • js: it's accessible (read/write) from js by the dataset property. Note dashes are converted to camelCase)

  • css: attr()

CSS

On make item invisible as well as clickable: https://css-tricks.com/snippets/css/toggle-visibility-when-hiding-elements/

Element CRUD

Update content

Observe Changes

The MutationObserver interface provides the ability to watch for changes being made to the DOM tree.

You can observe changes (child, attributes, style, etc) and pause in dev tools:

Common Functions

BOM

  • Reload window: location.reload();

  • Scroll to top: window.scrollTo(0, 0);

Don't use onclick: single property, essentially override it.

Event CRUD

Override Default Event

  • preventDefault() stop default handling, it'll still propagate

  • stopPropagation() stop bubbling up

  • stopImmediatePropagation() stop handling in current layer, stop passing to other event handlers: If several listeners are attached to the same element for the same event type, they are called in order in which they have been added. If during one such call, event.stopImmediatePropagation() is called, no remaining listeners will be called.

e.target vs e.currentTarget:

  • e.target identifies the element on which the event occurred

  • e.currentTarget always refer to the the element to which the event handler has been attached

this

  • usually points to the DOM element where the handler is bound.

  • NOTE if you add event using arrow function then it's document instead of the element!

How to trigger event manually:

https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events

How to perform click? element.click()

Keyboard/Mouse events:

Custom events

interface for any custom event:

Event Delegation

Use one event handler to handle all children events

Event delegation can also be used to add behavior to any element (with data-attr):

Last updated