DOM & Events
DOM Manipulation
Element Selection
// Single element
document.getElementById('myId');
document.querySelector('.myClass');
document.querySelector('#myId');
document.querySelector('div[data-id="123"]');
// Multiple elements
document.getElementsByClassName('myClass');
document.getElementsByTagName('div');
document.querySelectorAll('.myClass');
document.querySelectorAll('div.active');
// Relative selection
const parent = document.querySelector('.parent');
parent.querySelector('.child'); // Child of parent
parent.children; // Direct children
parent.firstElementChild; // First child
parent.lastElementChild; // Last child
parent.nextElementSibling; // Next sibling
parent.previousElementSibling; // Previous sibling
Element Manipulation
const element = document.querySelector('#myElement');
// Content
element.textContent = 'New text';
element.innerHTML = '<span>HTML content</span>';
element.innerText = 'Visible text only';
// Attributes
element.setAttribute('data-id', '123');
element.getAttribute('data-id');
element.removeAttribute('data-id');
element.hasAttribute('data-id');
// Data attributes
element.dataset.userId = '123'; // Sets data-user-id
const userId = element.dataset.userId; // Gets data-user-id
// Classes
element.classList.add('new-class');
element.classList.remove('old-class');
element.classList.toggle('active');
element.classList.contains('active');
element.classList.replace('old', 'new');
// Styles
element.style.color = 'red';
element.style.fontSize = '16px';
element.style.backgroundColor = 'blue';
// Computed styles
const styles = getComputedStyle(element);
const color = styles.getPropertyValue('color');
Element Creation & Insertion
// Create elements
const newDiv = document.createElement('div');
newDiv.textContent = 'Hello World';
newDiv.className = 'greeting';
newDiv.id = 'new-element';
// Create with HTML
const template = document.createElement('template');
template.innerHTML = `
<div class="card">
<h3>Title</h3>
<p>Content</p>
</div>
`;
const card = template.content.firstElementChild;
// Insert into DOM
document.body.appendChild(newDiv);
document.body.insertBefore(newDiv, existingElement);
existingElement.insertAdjacentElement('afterend', newDiv);
// insertAdjacentElement positions:
// 'beforebegin' - before the element
// 'afterbegin' - inside, before first child
// 'beforeend' - inside, after last child
// 'afterend' - after the element
// Insert HTML
element.insertAdjacentHTML('beforeend', '<p>New paragraph</p>');
// Remove elements
element.remove(); // Remove element
parent.removeChild(child); // Remove child
Element Properties
// Dimensions and position
element.offsetWidth; // Width including border
element.offsetHeight; // Height including border
element.clientWidth; // Width excluding border
element.clientHeight; // Height excluding border
element.scrollWidth; // Full scrollable width
element.scrollHeight; // Full scrollable height
// Position
element.offsetTop; // Distance from top
element.offsetLeft; // Distance from left
element.getBoundingClientRect(); // Position relative to viewport
// Scroll position
element.scrollTop; // Vertical scroll position
element.scrollLeft; // Horizontal scroll position
// Check visibility
function isInViewport(element) {
const rect = element.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= window.innerHeight &&
rect.right <= window.innerWidth
);
}
Event Handling
Event Listeners
// Add event listener
element.addEventListener('click', function (event) {
console.log('Clicked!');
});
// Arrow function with event
element.addEventListener('click', event => {
event.preventDefault(); // Prevent default behavior
event.stopPropagation(); // Stop event bubbling
console.log('Target:', event.target);
console.log('Current target:', event.currentTarget);
});
// Remove event listener
const handler = event => console.log('Clicked!');
element.addEventListener('click', handler);
element.removeEventListener('click', handler);
// Event options
element.addEventListener('scroll', handler, {
passive: true, // Never calls preventDefault
once: true, // Run only once
capture: true, // Capture phase
});
Event Types
Mouse Events
// Mouse events
element.addEventListener('click', handler);
element.addEventListener('dblclick', handler);
element.addEventListener('mousedown', handler);
element.addEventListener('mouseup', handler);
element.addEventListener('mouseover', handler);
element.addEventListener('mouseout', handler);
element.addEventListener('mouseenter', handler); // Doesn't bubble
element.addEventListener('mouseleave', handler); // Doesn't bubble
element.addEventListener('mousemove', handler);
// Mouse event properties
function handleMouseEvent(event) {
console.log('Mouse position:', event.clientX, event.clientY);
console.log('Button pressed:', event.button); // 0=left, 1=middle, 2=right
console.log('Ctrl key:', event.ctrlKey);
console.log('Shift key:', event.shiftKey);
console.log('Alt key:', event.altKey);
}
Keyboard Events
// Keyboard events
document.addEventListener('keydown', event => {
console.log('Key:', event.key); // 'Enter', 'Escape', 'a', etc.
console.log('Code:', event.code); // 'KeyA', 'Enter', etc.
console.log('Key code:', event.keyCode); // Deprecated
// Common key checks
if (event.key === 'Enter') {
console.log('Enter pressed');
}
if (event.key === 'Escape') {
console.log('Escape pressed');
}
// Modifier keys
if (event.ctrlKey && event.key === 's') {
event.preventDefault();
console.log('Ctrl+S pressed');
}
});
document.addEventListener('keyup', handler);
document.addEventListener('keypress', handler); // Deprecated
Form Events
const form = document.querySelector('form');
const input = document.querySelector('input');
// Form events
form.addEventListener('submit', event => {
event.preventDefault(); // Prevent form submission
const formData = new FormData(form);
console.log('Form data:', Object.fromEntries(formData));
});
form.addEventListener('reset', event => {
console.log('Form reset');
});
// Input events
input.addEventListener('input', event => {
console.log('Input value:', event.target.value);
});
input.addEventListener('change', event => {
console.log('Input changed:', event.target.value);
});
input.addEventListener('focus', event => {
console.log('Input focused');
});
input.addEventListener('blur', event => {
console.log('Input lost focus');
});
Window & Document Events
// Document events
document.addEventListener('DOMContentLoaded', () => {
console.log('DOM fully loaded');
});
// Window events
window.addEventListener('load', () => {
console.log('Page fully loaded (including images)');
});
window.addEventListener('beforeunload', event => {
event.preventDefault();
event.returnValue = ''; // Show confirmation dialog
});
window.addEventListener('resize', () => {
console.log('Window resized:', window.innerWidth, window.innerHeight);
});
window.addEventListener('scroll', () => {
console.log('Page scrolled:', window.pageYOffset);
});
Event Delegation
// Event delegation - handle events on parent
document.addEventListener('click', event => {
// Check if clicked element matches selector
if (event.target.matches('.button')) {
console.log('Button clicked:', event.target.textContent);
}
// Check if clicked element or ancestor matches
if (event.target.closest('.card')) {
console.log('Card clicked');
}
});
// Utility function for event delegation
function delegate(parent, selector, event, handler) {
parent.addEventListener(event, e => {
if (e.target.matches(selector)) {
handler(e);
}
});
}
// Usage
delegate(document, '.delete-btn', 'click', e => {
e.target.closest('.item').remove();
});
Custom Events
// Create custom event
const customEvent = new CustomEvent('myCustomEvent', {
detail: { message: 'Hello from custom event!' },
bubbles: true,
cancelable: true,
});
// Listen for custom event
element.addEventListener('myCustomEvent', event => {
console.log('Custom event:', event.detail.message);
});
// Dispatch custom event
element.dispatchEvent(customEvent);
// Event constructor with more options
const dataEvent = new CustomEvent('dataLoaded', {
detail: {
data: [1, 2, 3],
timestamp: Date.now(),
},
});
// Dispatch on different targets
document.dispatchEvent(dataEvent);
window.dispatchEvent(dataEvent);
Event Patterns
Debounced Events
function debounce(func, delay) {
let timeoutId;
return function (...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => func.apply(this, args), delay);
};
}
const debouncedSearch = debounce(event => {
console.log('Searching for:', event.target.value);
}, 300);
input.addEventListener('input', debouncedSearch);
Throttled Events
function throttle(func, limit) {
let inThrottle;
return function (...args) {
if (!inThrottle) {
func.apply(this, args);
inThrottle = true;
setTimeout(() => (inThrottle = false), limit);
}
};
}
const throttledScroll = throttle(() => {
console.log('Scroll position:', window.pageYOffset);
}, 100);
window.addEventListener('scroll', throttledScroll);
Event Cleanup
class Component {
constructor(element) {
this.element = element;
this.listeners = [];
this.setupEventListeners();
}
setupEventListeners() {
this.addListener('click', this.handleClick.bind(this));
this.addListener('input', this.handleInput.bind(this));
}
addListener(event, handler) {
this.element.addEventListener(event, handler);
this.listeners.push({ event, handler });
}
destroy() {
this.listeners.forEach(({ event, handler }) => {
this.element.removeEventListener(event, handler);
});
this.listeners = [];
}
handleClick(event) {
console.log('Component clicked');
}
handleInput(event) {
console.log('Component input:', event.target.value);
}
}