Published on

Notes on Browser JavaScript

Authors

Browser: Document, Events, Interfaces

  • Learning how to manage the browser page: Add elements, manipulate their size and position, dynamically create interfaces and interact with the visitor.

Document

  • Browser Environment & Specs:
    • Global Objects: window (global scope for browser APIs), document (entry point to DOM).
    • Client-side JavaScript runs in a host environment (browser), providing objects like window, document, navigator, screen, history, location.
    • Distinct from Node.js environment; different global objects and APIs.
  • DOM Tree:
    • Document Object Model (DOM): A programming interface for HTML/XML documents. Represents the page's structure as a tree of nodes.
    • Nodes: Elements (tags), text nodes, comment nodes, document type node (<!DOCTYPE html>), document object itself.
    • document: The root of the DOM tree.
  • Walking the DOM:
    • Navigation properties (all nodes):
      • elem.childNodes: Live NodeList of all direct children (including text/comment nodes).
      • elem.firstChild, elem.lastChild: First/last child node.
      • elem.parentNode: Parent node.
      • elem.nextSibling, elem.previousSibling: Next/previous sibling node.
    • Element-only navigation properties (recommended for most HTML tasks):
      • elem.children: Live HTMLCollection of direct element children.
      • elem.firstElementChild, elem.lastElementChild: First/last element child.
      • elem.parentElement: Parent element (same as parentNode for element nodes).
      • elem.nextElementSibling, elem.previousElementSibling: Next/previous element sibling.
  • Searching: getElement*, querySelector*:
    • document.getElementById('id'): Returns single element, very fast.
    • document.getElementsByName('name'): Live NodeList by name attribute.
    • document.getElementsByTagName('tag'): Live HTMLCollection by tag name.
    • document.getElementsByClassName('class'): Live HTMLCollection by class name.
    • elem.querySelector('css-selector'): Returns the first matching element, supports complex CSS selectors.
    • elem.querySelectorAll('css-selector'): Returns a static NodeList of all matching elements. More flexible but potentially slower for simple lookups.
    • Live vs. Static Collections: getElementsBy* methods return live collections (reflect DOM changes automatically). querySelectorAll returns static NodeList (snapshot at time of call).
  • Node Properties: Type, Tag & Contents:
    • nodeType: Numeric constant (e.g., Node.ELEMENT_NODE (1), Node.TEXT_NODE (3), Node.COMMENT_NODE (8), Node.DOCUMENT_NODE (9)).
    • nodeName / tagName: Tag name (uppercase for elements, e.g., "DIV"), nodeName for non-elements (e.g., "#text", "#comment", "#document").
    • textContent: Gets/sets only the text content of the element and all its descendants, stripping HTML tags. Safe from XSS.
    • innerHTML: Gets/sets the HTML content inside the element. Can include HTML tags. Vulnerable to XSS if used with untrusted data.
    • outerHTML: The full HTML of the element itself, including its outer tag.
  • Attributes and Properties:
    • HTML Attributes: Reflect attributes in HTML source. Accessed via:
      • elem.hasAttribute(name)
      • elem.getAttribute(name)
      • elem.setAttribute(name, value)
      • elem.removeAttribute(name)
    • DOM Properties: JavaScript object properties on the DOM node. Directly accessed as elem.propName.
    • Synchronization: Many HTML attributes have corresponding DOM properties (e.g., id, value, href). Changes to one usually reflect in the other, but not always (input.value vs input.getAttribute('value')).
    • data-* attributes: Custom attributes stored in dataset DOM property (e.g., <div data-key="value"> becomes elem.dataset.key).
  • Modifying the Document:
    • document.createElement(tagName): Creates a new element node.
    • document.createTextNode(text): Creates a new text node.
    • node.append(...nodes or strings): Appends nodes/strings to the end of node.
    • node.prepend(...nodes or strings): Prepends nodes/strings to the beginning of node.
    • node.before(...nodes or strings): Inserts nodes/strings before node.
    • node.after(...nodes or strings): Inserts nodes/strings after node.
    • node.replaceWith(...nodes or strings): Replaces node with new nodes/strings.
    • node.remove(): Removes node from its parent.
    • parent.insertBefore(newElem, referenceElem): Inserts newElem before referenceElem (older method).
    • parent.appendChild(newElem): Appends newElem to parent (older method).
    • elem.cloneNode(true/false): Clones element. true for deep clone (with children), false for shallow.
    • elem.insertAdjacentHTML(position, htmlString): Inserts HTML string at specified position ('beforebegin', 'afterbegin', 'beforeend', 'afterend'). Useful for fast HTML insertion without DOM node creation overhead.
  • Styles and Classes:
    • elem.style.prop: Gets/sets inline CSS properties (e.g., elem.style.backgroundColor = 'red'). Overwrites any existing inline style.
    • elem.style.cssText: Gets/sets all inline styles as a string.
    • getComputedStyle(elem, [pseudoElement]): Returns an object containing the computed values of all CSS properties of an element. Read-only. Accounts for stylesheets, inherited styles, etc.
    • elem.className: Gets/sets the entire class attribute string. Overwrites existing classes.
    • elem.classList: Provides methods to manage classes (preferred):
      • elem.classList.add('class')
      • elem.classList.remove('class')
      • elem.classList.toggle('class')
      • elem.classList.contains('class')
  • Element Size and Scrolling:
    • elem.offsetWidth/offsetHeight: Geometric width/height of the element, including padding, border, and scrollbar (if visible).
    • elem.clientWidth/clientHeight: Inner width/height, including padding but excluding border and scrollbar. Represents the content area.
    • elem.scrollWidth/scrollHeight: The full scrollable width/height of the element's content, including non-visible parts.
    • elem.scrollLeft/scrollTop: Gets/sets the horizontal/vertical scroll position of the element.
  • Window Sizes and Scrolling:
    • window.innerWidth/innerHeight: Viewport width/height, including scrollbar.
    • document.documentElement.clientWidth/clientHeight: Viewport width/height, excluding scrollbar. Often preferred for content area.
    • window.scrollX/scrollY (or window.pageXOffset/pageYOffset): Current scroll position of the document from the top-left corner.
    • window.scrollTo(x, y) / window.scrollBy(x, y): Programmatically scrolls the window.
  • Coordinates:
    • elem.getBoundingClientRect(): Returns a DOMRect object with left, top, right, bottom, width, height properties, representing the element's size and its position relative to the viewport.
    • document.documentElement.clientTop/clientLeft: Width of the top/left border of the document.documentElement (usually 0 unless CSS changes it).
    • elem.offsetParent: The nearest positioned ancestor element.
    • elem.offsetTop/offsetLeft: Position of elem relative to the top-left corner of offsetParent.

Introduction to Events

  • Introduction to Browser Events:
    • Actions or occurrences recognized by the browser, e.g., mouse clicks, key presses, page loads.
    • Event handlers/listeners: Functions executed when an event occurs. Registered using elem.addEventListener(event, handler, [options]).
    • event object: Passed to the handler, contains information about the event (type, target, coordinates, etc.).
  • Bubbling and Capturing:
    • Event Flow: When an event occurs on an element, it propagates through three phases:
      1. Capturing Phase: Event travels down from window to the event.target. Handlers registered with useCapture = true (or capture: true option) trigger here.
      2. Target Phase: Event reaches the event.target element.
      3. Bubbling Phase: Event travels up from event.target to window. Most common phase, default for addEventListener.
    • event.target: The actual element where the event originated.
    • event.currentTarget: The element on which the event listener is currently being executed.
    • event.stopPropagation(): Prevents bubbling (and capturing) beyond the current element.
    • event.stopImmediatePropagation(): Prevents bubbling and prevents other handlers on the same element from executing.
  • Event Delegation:
    • Attaching a single event listener to a parent element instead of multiple children.
    • Relies on event bubbling: The event bubbles up from the actual event.target to the parent.
    • The handler then uses event.target to identify which child originated the event and acts accordingly.
    • Benefits:
      • Performance: Fewer event listeners improve memory and performance.
      • Dynamic Elements: Works automatically for elements added/removed after the initial setup.
      • Cleaner Code: Centralizes event handling logic.
  • Browser Default Actions:
    • Many browser events have default actions (e.g., clicking a link navigates, submitting a form reloads).
    • event.preventDefault(): Stops the default browser action for an event.
    • return false: An older way to prevent default action for handlers assigned via on<event> HTML attributes or DOM properties (e.g., elem.onclick = function() { return false; }). Not applicable for addEventListener.
  • Dispatching Custom Events:
    • new Event(name, [options]): Creates a generic custom event. Options include bubbles: true/false, cancelable: true/false.
    • new CustomEvent(name, { detail: data, ...options }): Creates a custom event with a detail property for carrying arbitrary data.
    • elem.dispatchEvent(event): Dispatches the created event on the specified element. The event then propagates as per bubbling/capturing rules.

UI Events

  • Mouse Events:
    • click: Fired on mousedown followed by mouseup on the same element.
    • dblclick: Fired on two click events in rapid succession.
    • mousedown, mouseup: Fired when a mouse button is pressed/released.
    • mousemove: Fired when the mouse pointer moves over an element.
    • contextmenu: Fired when the right mouse button is clicked (or equivalent action) on an element.
    • event.clientX/clientY: Mouse coordinates relative to the viewport.
    • event.pageX/pageY: Mouse coordinates relative to the document.
    • event.button: Which mouse button was pressed (0: left, 1: middle, 2: right).
  • Moving the Mouse: mouseover/out, mouseenter/leave:
    • mouseover: Fired when the mouse pointer enters an element or any of its descendants. Bubbles.
    • mouseout: Fired when the mouse pointer leaves an element or moves into one of its descendants. Bubbles.
    • mouseenter: Fired when the mouse pointer enters an element. Does not bubble. Only fires for the element itself, not its descendants.
    • mouseleave: Fired when the mouse pointer leaves an element. Does not bubble.
    • event.relatedTarget: The element that the mouse pointer entered from (mouseout, mouseleave) or exited to (mouseover, mouseenter). Crucial for managing transitions between elements.
  • Drag'n'Drop with Mouse Events:
    • Implemented by combining mousedown (start drag), mousemove (track drag), and mouseup (end drag).
    • Requires preventing default browser text selection or image dragging.
    • Can involve modifying CSS (e.g., position: absolute) and z-index for the dragged element.
  • Pointer Events:
    • A unified event model for all input pointer devices (mouse, pen, touch).
    • Provides consistent events across different input types.
    • Events: pointerdown, pointermove, pointerup, pointercancel, pointerover, pointerout, pointerenter, pointerleave, gotpointercapture, lostpointercapture.
    • event.pointerId: Unique ID for the pointer (e.g., specific finger or mouse).
    • event.isPrimary: true if this is the primary pointer for a multitouch/multi-input interaction.
    • elem.setPointerCapture(pointerId): Designates elem to receive all subsequent pointer events for pointerId, regardless of pointer position.
    • elem.releasePointerCapture(pointerId): Releases pointer capture.
  • Keyboard: keydown and keyup:
    • keydown: Fired when a key is pressed. Fires repeatedly if held down (event.repeat).
    • keyup: Fired when a key is released.
    • event.key: Represents the character value of the key (e.g., "A", "Enter", "F5", "ArrowLeft").
    • event.code: Represents the physical key code (e.g., "KeyA", "Enter", "F5", "ArrowLeft"). Stable across keyboard layouts.
    • Modifier keys: event.ctrlKey, event.shiftKey, event.altKey, event.metaKey (Command on Mac, Windows key on Windows).
  • Scrolling:
    • scroll event: Fired when an element or the document view is scrolled.
    • Often triggers frequently, so throttling or debouncing handlers is crucial for performance.
    • Can check document.documentElement.scrollTop/scrollLeft (for document) or elem.scrollTop/scrollLeft (for specific elements).

Forms, Controls

  • Form Properties and Methods:
    • form.elements: A collection (NodeList) of all form controls (input, textarea, select, button).
    • form.elements.name: Access control by its name attribute.
    • form.submit(): Programmatically submits the form. Does not trigger the submit event.
    • form.reset(): Resets all form fields to their initial values. Does not trigger the reset event.
  • Focusing: focus/blur:
    • focus: Fired when an element receives focus (e.g., via click, tab, elem.focus()). Does not bubble.
    • blur: Fired when an element loses focus. Does not bubble.
    • For bubbling behavior, use focusin (bubbles when element gains focus) and focusout (bubbles when element loses focus).
    • elem.focus(): Programmatically sets focus to an element.
    • elem.blur(): Programmatically removes focus from an element.
    • document.activeElement: Returns the currently focused element in the document.
  • Events: change, input, cut, copy, paste:
    • change: Fired when an element's value is committed.
      • For input type="text", textarea, select: Fired when value changes and element loses focus (blurs).
      • For input type="checkbox", radio: Fired immediately when checked/unchecked.
    • input: Fired immediately when the value of an input or textarea element is changed by the user (e.g., on every keystroke).
    • cut, copy, paste: Fired when text is cut, copied, or pasted. event.clipboardData object provides access to clipboard data.
  • Forms: event and method submit:
    • submit event: Fired on the <form> element when the form is submitted (e.g., by clicking type="submit" button, pressing Enter in an input field). Can be prevented using event.preventDefault() to handle submission via AJAX.
    • form.submit() method: See above (Form Properties and Methods). It's a method call, not an event dispatch.

Document and Resource Loading

  • Page: DOMContentLoaded, load, beforeunload, unload:
    • DOMContentLoaded: Fired when the initial HTML document has been completely loaded and parsed, without waiting for stylesheets, images, and subframes to finish loading. The DOM is ready for interaction.
    • load: Fired when the entire page, including all dependent resources (images, stylesheets, scripts, etc.), has been fully loaded.
    • beforeunload: Fired when the user is about to navigate away from the page (e.g., closing tab, clicking link, submitting form). Allows preventing navigation with a confirmation dialog (browser-specific).
    • unload: Fired when the document is being unloaded. Limited reliability and functionality due to browsers restricting operations to prevent issues. Only very basic, non-blocking operations are possible.
  • Scripts: async, defer:
    • <script> (no attributes): Parser blocks, script downloads, executes, then parser resumes. Blocking.
    • <script async>: Downloads asynchronously, executes as soon as downloaded (regardless of HTML parsing completion or other script order). Non-blocking, order not guaranteed. Use for independent scripts.
    • <script defer>: Downloads asynchronously, executes after HTML parsing is complete (just before DOMContentLoaded), maintains relative order with other defer scripts. Non-blocking, order guaranteed for defer scripts. Ideal for most scripts that interact with the DOM.
  • Resource Loading: onload and onerror:
    • Events for individual resources (<img>, <script>, <link>, <iframe>).
    • resource.onload: Fired when the resource has successfully loaded.
    • resource.onerror: Fired when an error occurs during resource loading.

Miscellaneous

  • Mutation Observer:
    • An API to observe changes made to the DOM tree. Provides a way to react to modifications.
    • new MutationObserver(callback): Creates an observer instance. The callback receives a list of MutationRecord objects describing the changes.
    • observer.observe(targetNode, options): Configures the observer to watch targetNode for specified types of changes.
      • options: Object specifying what to observe (e.g., childList: true, attributes: true, subtree: true, characterData: true).
    • observer.disconnect(): Stops the observer from receiving further notifications.
    • observer.takeRecords(): Returns any pending MutationRecord objects and empties the observer's record queue.
    • Use Cases: Reacting to dynamic content loading, implementing virtual DOM, monitoring third-party script changes.
  • Selection and Range:
    • Selection: Represents the user's current text selection.
      • window.getSelection(): Returns a Selection object.
      • Properties: anchorNode, anchorOffset (start of selection), focusNode, focusOffset (end of selection), isCollapsed (true if no text is selected).
      • Methods: addRange(), removeRange(), removeAllRanges(), toString() (gets selected text).
    • Range: A contiguous portion of the DOM tree. Can represent a selection, but also arbitrary parts of the document.
      • document.createRange(): Creates an empty Range object.
      • Methods:
        • range.setStart(node, offset), range.setEnd(node, offset): Define range boundaries.
        • range.selectNode(node), range.selectNodeContents(node): Select entire nodes or their contents.
        • range.deleteContents(): Removes content within the range.
        • range.extractContents(): Removes content and returns it as a DocumentFragment.
        • range.surroundContents(newParentNode): Wraps the range's content with newParentNode.
      • Use Cases: Implementing rich text editors, custom text highlighting, manipulating specific document fragments.

Event Loop: Microtasks and Macrotasks

  • Event Loop: The fundamental concurrency model in JavaScript (and browsers/Node.js). It continuously checks the call stack, macrotask queue, and microtask queue to decide what code to execute next.
    • Ensures non-blocking I/O operations by offloading tasks and executing their callbacks later.
    • A single-threaded model, but gives the illusion of concurrency.
  • Macrotasks (Tasks):
    • Represent a "big" unit of work. Only one macrotask is processed per turn of the event loop.
    • After a macrotask completes, the browser renders (if needed) and then the event loop processes all available microtasks.
    • Common Sources:
      • setTimeout()
      • setInterval()
      • UI rendering events (e.g., requestAnimationFrame is often associated with rendering)
      • I/O operations (e.g., network requests like fetch response, XMLHttpRequest)
      • Script execution (the main script itself is an initial macrotask)
      • MessageChannel callbacks
  • Microtasks (Jobs):
    • Represent a "small" unit of work. The microtask queue is processed completely after the current macrotask finishes and before the next macrotask starts (or before rendering).
    • If a microtask adds new microtasks, those new microtasks are also processed in the same microtask queue turn. This can lead to "microtask starvation" if not managed carefully.
    • Common Sources:
      • Promise callbacks (.then(), .catch(), .finally())
      • await callbacks (resume after promise resolves)
      • queueMicrotask()
      • MutationObserver callbacks
  • Processing Order (Simplified Cycle):
    1. Execute one macrotask from the macrotask queue (or initial script).
    2. After the macrotask finishes, process all microtasks in the microtask queue.
    3. If microtasks add more microtasks, process them immediately until the microtask queue is empty.
    4. Perform browser rendering updates (if any changes were made and time allows).
    5. Repeat the cycle, taking the next macrotask.
  • Key Takeaway: Microtasks have higher priority than macrotasks. They run immediately after the currently executing script/macrotask, before the browser gets a chance to render or run another macrotask.

Related Posts