Adding Buttons
Quick Method
Add attribute onClick='functionName()' to the desired element
// In HTML
<button class="menu-btn" id="menuBtn" onClick="myFunction()">☰</button>
<script>
function myFunction() {
console.log("Button clicked!");
}
</script>Modular Method
Use addEventListener() to bind the element to the function and the 'click' event
// In HTML
<head>
<script type="module">
import { bindButton } from '/load-menu.js';
document.addEventListener('DOMContentLoaded', () => {// wrap the callback function
(bindButton) in a function so it doesn't run immediately when script loads
// Bind button after DOM is loaded
<mark>bindButton("menuBtn");</mark>
});
</script>
</head>
<body>
<button class="menu-btn" <mark>id="menuBtn">&#9776;</button>
</body>// In load-menu.js
// Function to bind button click event
export function bindButton(buttonId) {
document.getElementById(buttonId).addEventListener('click', myFunction);>
}
// Declare the function to be called when button clicked
function myFunction() {
console.log("Button clicked!");
}Finding Elements
The main methods for getting an element in the DOM are getElementById,querySelector, querySelectorAll
getElementByIdcan only be used byDocumentobjects (i.e.document)querySelectorandquerySelectorAllcan be used by bothHTMLElementandDocumentobjects
// In Javascript
// Returns the element with id="menuBtn"
const menuBtn = document.getElementById("menuBtn");
// Returns the first button element with class="menu-btn"
const menuBtn = document.querySelector("button .menu-btn");
// Returns a NodeList of all button elements with class="menu-btn"
const menuBtns = document.querySelectorAll("button .menu-btn");
// Looking for a #menuBtn starting from a specific element, topNav
const topNav = document.getElementById("topNav");
const menuBtn = topNav.querySelector("#menuBtn");Element Object
The Element object has generic DOM manipulation methods and properties.
Commonly Used Methods and Properties
querySelector(selector): Returns the first matching descendant element.querySelectorAll(selector): Returns a NodeList of all matching descendants.getAttribute(name)/setAttribute(name, value)/removeAttribute(name): Attribute handling.document.documentElement.setAttribute('data-theme', 'dark'): add the custom attributedata-theme='dark'to the root-level element (i.e.<html$gt;element)- Very useful to change the 'state' of the overall site
append(...nodesOrStrings)/prepend(...nodesOrStrings): Insert content inside the element.document.body.prepend(node): add a node as the first child of the<body>before(...nodesOrStrings)/after(...nodesOrStrings)/replaceWith(...nodesOrStrings): Insert or replace relative to the element itself.oldTopNav.replaceWith(newTopNav): replace the old top nav element with the newly created oneclassList: Property with methods likeadd(),remove(),toggle(),contains().leftNav.classList.toggle('open'): add/ remove the class 'open' from the element leftNav- Very useful to switch the 'state' of an element
Other Methods and Properties
hasAttribute(name): Check if attribute exists.matches(selector): Checks if the element would be selected by a given CSS selector.closest(selector): Finds the nearest ancestor (including itself) matching a selector.remove(): Removes the element from the DOM.
Reference: developer.mozilla.org/en-US/docs/Web/API/Element
HTMLElement Object
style: Access inline CSS styling via JS (e.g.,element.style.color = 'red').innerText/innerHTML/outerHTML: Get or set the element's content.focus()/blur(): Manage element focus.click(): Programmatically triggers a click event.hidden: Boolean property to toggle whether the element is hidden.tabIndex: Controls keyboard tab navigation order.contentEditable: Makes element text editable in the browser.dataset: Accessdata-*attributes (e.g.,div.dataset.id).
Reference: developer.mozilla.org/en-US/docs/Web/API/HTMLElement
Creating Elements
Creating Elements
Use document.createElement('template') to create a template element where theinnerHTML can be replaced with new element's code
// In Javascript
// raw HTML code for the new button
const btnHTML = `
<button class="menu-btn" id="menuBtn">&#9776;</button>
`;
// Create a new button element
function createButton() {
const btnTemp = document.createElement('template');
btnTemp.innerHTML = btnHTML.trim(); // Set the HTML code
const newBtn = btnTemp.content.firstChild; // Get the element node
return newBtn;
}Notes
- Use backticks ` in order to create a template literal string - string in Javascript that spans multiple lines and uses embedded expression ( i.e. ${variableName} )
- Use
content.childrento get all the nodes if multiple elements were created
Editing DOM
Adding Elements
Use methods like prepend(), append(), before(), andafter() to add element(s) into the DOM
// In Javascript
const topNav = createTopNav(); // Create the top nav element
document.body.prepend(topNav); // Add the top nav as the first child of the bodyReplacing Elements
Use replaceWith() method to replace element.
// In Javascript
const topNav = createTopNav(); // Create the top nav element
const oldTopNav = document.getElementById('topNav'); // Get the old top nav element
oldTopNav.replaceWith(topNav); // Replace the old top nav with the new oneGetting and Setting Element Styles
- Use
window.getComputedStyle(element).getPropertyValue('css-property')to get the current property value as a String - To SET the inline property styles, use
element.style.cssProperty - Trying to read the CSS property value with
element.style.cssPropertycan give an empty string because it reads the inline value
// Reading the CSS property rule
const grid = document.getElementById('grid');
const rowTrackHeightString = window.getComputedStyle(grid).getPropertyValue('grid-auto-rows');
rowTrackHeight = parseInt(rowTrackHeightString);
// Setting the inline style
grid.style.gridAutoRows = someValueGetting Element Sizes
Generic HTML Element Properties
style.width / style.height: Inline style value, as a String; if not set, returns empty stringclientWidth / clientHeight: inner size of the element as an integer (includes padding, but excludes borders)offsetWidth / offsetHeight: Rendered size as an integer (includes padding + border)getBoundingClientRect().width / height: Precise rendered size as a float (reflects transforms and includes padding + border)getComputedStyle(element).width / height: Resolved CSS width/height value (e.g., '200px' or 'auto')
Image-, Video-, & Canvas-only Sizes
img.naturalWidth / img.naturalHeight: Actual image size in pixels (only for <img>)video.videoWidth / video.videoHeight: Actual video resolution (only for <video>)canvas.width / canvas.height: Internal drawing buffer size (only for <canvas>)img.width/height & video.width/height: Reflects the HTML attributes; sets rendered size (not intrinsic)
Local/Session Storage
localStorage is a persistent data storage for the web unlike sessionStorageunless the user is incognito mode, clears cookies, or storage is full
Methods
localStorage.setItem(key, value): Store a key-value pair.localStorage.getItem(key): Retrieve the value for a given key.localStorage.removeItem(key): Remove a key-value pair.localStorage.clear(): Clear all local storage data.
Notes
sessionStoragehas the same methods, but the data insessionStorageis only kept for the duration of the page session
Managing States
CSS classes can be used to define the state of an element
<nav className='menu'>: the menu is closed- In CSS code:
.menu
- In CSS code:
<nav className='menu open'>: the menu is open- In CSS code:
.menu.open
- In CSS code:
Managing State of Elements
Use methods like classList.add('open'), classList.remove('open'),classList.toggle('open'), and classList.contains('open') to handle CSS classes
// In Javascript
// Get the element
const leftNav = document.getElementById('leftNav');
// Toggle the menu's state
leftNav.classList.toggle('open'); // add/remove the class 'open' from the element leftNavManaging State of Whole Site
Use setAttribute(), removeAttribute() and getAttribute() methods alongside localStorage and document.documentElement to manage the whole site states
// In Javascript
// Set the theme to dark and store it
document.documentElement.setAttribute('data-theme', 'dark');
localStorage.setItem('data-theme', 'dark');
// Get the current theme
const currentTheme = localStorage.getItem('data-theme') ? localStorage.getItem('data-theme') : null;
if(currentTheme){
document.documentElement.setAttribute('data-theme', currentTheme);
}Reloading Sessions
Most browsers automatically save sessions up to a certain point, but for more complicated pages,sessionStorage can be used to save the states of a session
sessionStoragedata gets deleted when the user closes the tab or window.localStorageand IndexedDB can be used for more persistent data
Restore by pageshow (bfcache)
Sometimes back clicks cannot be detected and all page loads are treated as normal loads. In those cases, this method is more reliable.
<script type='module'>
// Do what is not saved here so it will run every time page loads
getTheme();
loadMenu('mainContainer', 'rightNav');
document.getElementById(loadBtnId).addEventListener('click', () => {
loadMasonryImages(gridId);
});
// Save gallery and scroll state before leaving page
window.addEventListener('beforeunload', saveGalleryState);
// Save the state of certain elements
function saveGalleryState() {
const gallery = document.getElementById(gridId);
sessionStorage.setItem('galleryHTML', gallery.innerHTML);
sessionStorage.setItem('galleryItemsCount', gallery.childElementCount);
sessionStorage.setItem('scrollPos', window.scrollY);
}
// Reload what was saved
function restoreGalleryState() {
const savedHTML = sessionStorage.getItem('galleryHTML');
if (savedHTML) {
const gallery = document.getElementById(gridId);
gallery.innerHTML = savedHTML;
updateImageCount(sessionStorage.getItem('galleryItemsCount'));
window.scrollTo(0, sessionStorage.getItem('scrollPos') || 0);
return true;
}
return false;
}
// What to make once and reload from session if possible
function makeOnce() {
loadMasonryImages(gridId);
}
// Listen for pageshow (bfcache) and normal load
window.addEventListener('pageshow', (event) => {
// If restored from bfcache, DOM is already there
if (event.persisted) {
console.log('Page restored from bfcache');
restoreGalleryState();
} else {
console.log('Normal page load');
makeOnce();
}
});
</script>Restoring by manually listening for entries event
Use performance.getEntriesByType('navigation')[0].type to get the last navigation method used to enter the page. This is more reliable than the previous method.
window.addEventListener('load', () => {
const navType = performance.getEntriesByType('navigation')[0].type;
if (navType === 'back_forward') {
console.log('Back/Forward navigation — restoring gallery');
restoreGalleryState();
} else {
console.log('Normal load — initialize page');
initPage();
}
});Other navigation.type values:
'navigate': normal load'reload': reload'back_forward': user navigated via back/forward
addEventListener
addEventListener() method allows the site to listen for when certain events are triggered on the specified element
addEventListener(type, listenerFunc)typeis the type of event to listen for (e.g., 'click', 'mouseover', 'keyup', 'DOMContentLoaded', 'resize', 'scroll', 'load', 'unload')listenerFuncis the function to be called when the event is triggered- Example:
menuBtn.addEventListener('click', () => myFunction)
Types of Events
- Mouse Events
click: Mouse click on an elementdblclick: Double-clickmousedown / mouseup: Mouse button pressed/releasedmousemove: Mouse moves over an elementmouseenter / mouseleave: Mouse enters/leaves an element (no bubbling)mouseover / mouseout: Mouse enters/leaves an element (bubbles)contextmenu: Right-click context menu
- Keyboard Events
keydown: Key is pressed downkeypress: Key is pressed (deprecated, use keydown)keyup: Key is released
- Form & Input Events
submit: Form submissionchange: Input/select value changesinput: Input value changes (real-time)focus / blur: Element gains or loses focusfocusin / focusout: Similar to focus/blur but bubbles
- Window / Document Events
load: Page or resource fully loadedDOMContentLoaded: DOM fully parsedresize: Window size changesscroll: Scrolling occursbeforeunload / unload: Page is about to leave
- Drag & Drop Events
dragstart, drag, dragenddragenter, dragover, dragleave, drop
- Clipboard Events
copy, cut, paste
- Touch Events
touchstart, touchmove, touchend, touchcancel
- Media Events
play, pause, ended, volumechange, timeupdate
- Pointer Events
pointerdown, pointerup, pointermove, pointerenter, pointerleave, pointercancel
- Miscellaneous Events
contextmenu: Right-click menuwheel: Mouse wheel scrollanimationstart, animationend, animationiterationtransitionstart, transitionend, transitionrun