mirror of
https://github.com/github/awesome-copilot.git
synced 2026-03-12 12:15:12 +00:00
* new skill web-coder * codespellrc: add aNULL HTTPS config cipher string * Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Apply suggestions from code review * Apply suggestion from @jhauga --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
655 lines
16 KiB
Markdown
655 lines
16 KiB
Markdown
# Web APIs & DOM Reference
|
|
|
|
Comprehensive reference for the Document Object Model (DOM) and Web APIs available in modern browsers.
|
|
|
|
## Document Object Model (DOM)
|
|
|
|
### What is the DOM?
|
|
The DOM is a programming interface for HTML and XML documents. It represents the page structure as a tree of objects that can be manipulated with JavaScript.
|
|
|
|
**DOM Tree Structure**:
|
|
```
|
|
Document
|
|
└── html
|
|
├── head
|
|
│ ├── title
|
|
│ └── meta
|
|
└── body
|
|
├── header
|
|
├── main
|
|
└── footer
|
|
```
|
|
|
|
### DOM Node Types
|
|
|
|
| Node Type | Description | Example |
|
|
|-----------|-------------|---------|
|
|
| Element | HTML element | `<div>`, `<p>` |
|
|
| Text | Text content | Text inside elements |
|
|
| Comment | HTML comment | `<!-- comment -->` |
|
|
| Document | Root document | `document` |
|
|
| DocumentFragment | Lightweight document | For batch operations |
|
|
|
|
### Selecting Elements
|
|
|
|
```javascript
|
|
// By ID
|
|
const element = document.getElementById('myId');
|
|
|
|
// By class name (returns HTMLCollection)
|
|
const elements = document.getElementsByClassName('myClass');
|
|
|
|
// By tag name (returns HTMLCollection)
|
|
const divs = document.getElementsByTagName('div');
|
|
|
|
// Query selector (first match)
|
|
const first = document.querySelector('.myClass');
|
|
const advanced = document.querySelector('div.container > p:first-child');
|
|
|
|
// Query selector all (returns NodeList)
|
|
const all = document.querySelectorAll('.myClass');
|
|
|
|
// Special selectors
|
|
document.body; // Body element
|
|
document.head; // Head element
|
|
document.documentElement; // <html> element
|
|
```
|
|
|
|
### Traversing the DOM
|
|
|
|
```javascript
|
|
const element = document.querySelector('#myElement');
|
|
|
|
// Parent
|
|
element.parentElement;
|
|
element.parentNode;
|
|
|
|
// Children
|
|
element.children; // HTMLCollection of child elements
|
|
element.childNodes; // NodeList of all child nodes
|
|
element.firstElementChild;
|
|
element.lastElementChild;
|
|
|
|
// Siblings
|
|
element.nextElementSibling;
|
|
element.previousElementSibling;
|
|
|
|
// Closest ancestor matching selector
|
|
element.closest('.container');
|
|
|
|
// Check if element contains another
|
|
parent.contains(child); // true/false
|
|
```
|
|
|
|
### Creating and Modifying Elements
|
|
|
|
```javascript
|
|
// Create element
|
|
const div = document.createElement('div');
|
|
const text = document.createTextNode('Hello');
|
|
const fragment = document.createDocumentFragment();
|
|
|
|
// Set content
|
|
div.textContent = 'Plain text'; // Safe (escaped)
|
|
div.innerHTML = '<strong>HTML</strong>'; // Can be unsafe with user input
|
|
|
|
// Set attributes
|
|
div.setAttribute('id', 'myDiv');
|
|
div.setAttribute('class', 'container');
|
|
div.id = 'myDiv'; // Direct property
|
|
div.className = 'container';
|
|
div.classList.add('active');
|
|
div.classList.remove('inactive');
|
|
div.classList.toggle('visible');
|
|
div.classList.contains('active'); // true/false
|
|
|
|
// Set styles
|
|
div.style.color = 'red';
|
|
div.style.backgroundColor = 'blue';
|
|
div.style.cssText = 'color: red; background: blue;';
|
|
|
|
// Data attributes
|
|
div.dataset.userId = '123'; // Sets data-user-id="123"
|
|
div.getAttribute('data-user-id'); // "123"
|
|
|
|
// Insert into DOM
|
|
parent.appendChild(div); // Add as last child
|
|
parent.insertBefore(div, referenceNode); // Insert before reference
|
|
parent.prepend(div); // Add as first child (modern)
|
|
parent.append(div); // Add as last child (modern)
|
|
element.after(div); // Insert after element
|
|
element.before(div); // Insert before element
|
|
element.replaceWith(newElement); // Replace element
|
|
|
|
// Remove from DOM
|
|
element.remove(); // Modern way
|
|
parent.removeChild(element); // Old way
|
|
|
|
// Clone element
|
|
const clone = element.cloneNode(true); // true = deep clone (with children)
|
|
```
|
|
|
|
### Element Properties
|
|
|
|
```javascript
|
|
// 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; // Total scrollable width
|
|
element.scrollHeight; // Total scrollable height
|
|
element.offsetTop; // Top position relative to offsetParent
|
|
element.offsetLeft; // Left position relative to offsetParent
|
|
|
|
// Bounding box
|
|
const rect = element.getBoundingClientRect();
|
|
// Returns: { x, y, width, height, top, right, bottom, left }
|
|
|
|
// Scroll position
|
|
element.scrollTop; // Vertical scroll position
|
|
element.scrollLeft; // Horizontal scroll position
|
|
element.scrollTo(0, 100); // Scroll to position
|
|
element.scrollIntoView(); // Scroll element into view
|
|
|
|
// Check visibility
|
|
element.checkVisibility(); // Modern API
|
|
```
|
|
|
|
## Event Handling
|
|
|
|
### Adding Event Listeners
|
|
|
|
```javascript
|
|
// addEventListener (modern, recommended)
|
|
element.addEventListener('click', handleClick);
|
|
element.addEventListener('click', handleClick, { once: true }); // Remove after first trigger
|
|
|
|
function handleClick(event) {
|
|
console.log('Clicked!', event);
|
|
}
|
|
|
|
// Event options
|
|
element.addEventListener('scroll', handleScroll, {
|
|
passive: true, // Won't call preventDefault()
|
|
capture: false, // Bubble phase (default)
|
|
once: true // Remove after one call
|
|
});
|
|
|
|
// Remove event listener
|
|
element.removeEventListener('click', handleClick);
|
|
```
|
|
|
|
### Common Events
|
|
|
|
| Category | Events |
|
|
|----------|--------|
|
|
| Mouse | `click`, `dblclick`, `mousedown`, `mouseup`, `mousemove`, `mouseenter`, `mouseleave`, `contextmenu` |
|
|
| Keyboard | `keydown`, `keyup`, `keypress` (deprecated) |
|
|
| Form | `submit`, `change`, `input`, `focus`, `blur`, `invalid` |
|
|
| Window | `load`, `DOMContentLoaded`, `resize`, `scroll`, `beforeunload`, `unload` |
|
|
| Touch | `touchstart`, `touchmove`, `touchend`, `touchcancel` |
|
|
| Drag | `drag`, `dragstart`, `dragend`, `dragover`, `drop` |
|
|
| Media | `play`, `pause`, `ended`, `timeupdate`, `loadeddata` |
|
|
| Animation | `animationstart`, `animationend`, `animationiteration` |
|
|
| Transition | `transitionstart`, `transitionend` |
|
|
|
|
### Event Object
|
|
|
|
```javascript
|
|
element.addEventListener('click', (event) => {
|
|
// Target elements
|
|
event.target; // Element that triggered event
|
|
event.currentTarget; // Element with listener attached
|
|
|
|
// Mouse position
|
|
event.clientX; // X relative to viewport
|
|
event.clientY; // Y relative to viewport
|
|
event.pageX; // X relative to document
|
|
event.pageY; // Y relative to document
|
|
|
|
// Keyboard
|
|
event.key; // 'a', 'Enter', 'ArrowUp'
|
|
event.code; // 'KeyA', 'Enter', 'ArrowUp'
|
|
event.ctrlKey; // true if Ctrl pressed
|
|
event.shiftKey; // true if Shift pressed
|
|
event.altKey; // true if Alt pressed
|
|
event.metaKey; // true if Meta/Cmd pressed
|
|
|
|
// Control event flow
|
|
event.preventDefault(); // Prevent default action
|
|
event.stopPropagation(); // Stop bubbling
|
|
event.stopImmediatePropagation(); // Stop other listeners
|
|
});
|
|
```
|
|
|
|
### Event Delegation
|
|
|
|
Handle events on parent instead of individual children:
|
|
|
|
```javascript
|
|
// Instead of adding listener to each button
|
|
document.querySelector('.container').addEventListener('click', (event) => {
|
|
if (event.target.matches('button')) {
|
|
console.log('Button clicked:', event.target);
|
|
}
|
|
});
|
|
```
|
|
|
|
## Web Storage APIs
|
|
|
|
### LocalStorage
|
|
|
|
Persistent storage (no expiration):
|
|
|
|
```javascript
|
|
// Set item
|
|
localStorage.setItem('key', 'value');
|
|
localStorage.setItem('user', JSON.stringify({ name: 'John' }));
|
|
|
|
// Get item
|
|
const value = localStorage.getItem('key');
|
|
const user = JSON.parse(localStorage.getItem('user'));
|
|
|
|
// Remove item
|
|
localStorage.removeItem('key');
|
|
|
|
// Clear all
|
|
localStorage.clear();
|
|
|
|
// Get key by index
|
|
localStorage.key(0);
|
|
|
|
// Number of items
|
|
localStorage.length;
|
|
|
|
// Iterate all items
|
|
for (let i = 0; i < localStorage.length; i++) {
|
|
const key = localStorage.key(i);
|
|
const value = localStorage.getItem(key);
|
|
console.log(key, value);
|
|
}
|
|
```
|
|
|
|
### SessionStorage
|
|
|
|
Storage cleared when tab closes:
|
|
|
|
```javascript
|
|
// Same API as localStorage
|
|
sessionStorage.setItem('key', 'value');
|
|
sessionStorage.getItem('key');
|
|
sessionStorage.removeItem('key');
|
|
sessionStorage.clear();
|
|
```
|
|
|
|
**Storage Limits**: ~5-10MB per origin
|
|
|
|
## Fetch API
|
|
|
|
Modern API for HTTP requests:
|
|
|
|
```javascript
|
|
// Basic GET request
|
|
fetch('https://api.example.com/data')
|
|
.then(response => response.json())
|
|
.then(data => console.log(data))
|
|
.catch(error => console.error(error));
|
|
|
|
// Async/await
|
|
async function fetchData() {
|
|
try {
|
|
const response = await fetch('https://api.example.com/data');
|
|
|
|
// Check if successful
|
|
if (!response.ok) {
|
|
throw new Error(`HTTP error! status: ${response.status}`);
|
|
}
|
|
|
|
const data = await response.json();
|
|
return data;
|
|
} catch (error) {
|
|
console.error('Fetch error:', error);
|
|
}
|
|
}
|
|
|
|
// POST request with JSON
|
|
fetch('https://api.example.com/users', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify({ name: 'John', age: 30 })
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => console.log(data));
|
|
|
|
// With various options
|
|
fetch(url, {
|
|
method: 'GET', // GET, POST, PUT, DELETE, etc.
|
|
headers: {
|
|
'Authorization': 'Bearer token',
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify(data), // For POST/PUT
|
|
mode: 'cors', // cors, no-cors, same-origin
|
|
credentials: 'include', // include, same-origin, omit
|
|
cache: 'no-cache', // default, no-cache, reload, force-cache
|
|
redirect: 'follow', // follow, error, manual
|
|
referrerPolicy: 'no-referrer' // no-referrer, origin, etc.
|
|
});
|
|
|
|
// Response methods
|
|
const text = await response.text(); // Plain text
|
|
const json = await response.json(); // JSON
|
|
const blob = await response.blob(); // Binary data
|
|
const arrayBuffer = await response.arrayBuffer(); // ArrayBuffer
|
|
const formData = await response.formData(); // FormData
|
|
```
|
|
|
|
## Other Important Web APIs
|
|
|
|
### Console API
|
|
|
|
```javascript
|
|
console.log('Message'); // Log message
|
|
console.error('Error'); // Error message (red)
|
|
console.warn('Warning'); // Warning message (yellow)
|
|
console.info('Info'); // Info message
|
|
console.table([{ a: 1 }, { a: 2 }]); // Table format
|
|
console.group('Group'); // Start group
|
|
console.groupEnd(); // End group
|
|
console.time('timer'); // Start timer
|
|
console.timeEnd('timer'); // End timer and log duration
|
|
console.clear(); // Clear console
|
|
console.assert(condition, 'Error message'); // Assert condition
|
|
```
|
|
|
|
### Timers
|
|
|
|
```javascript
|
|
// Execute once after delay
|
|
const timeoutId = setTimeout(() => {
|
|
console.log('Executed after 1 second');
|
|
}, 1000);
|
|
|
|
// Cancel timeout
|
|
clearTimeout(timeoutId);
|
|
|
|
// Execute repeatedly
|
|
const intervalId = setInterval(() => {
|
|
console.log('Executed every second');
|
|
}, 1000);
|
|
|
|
// Cancel interval
|
|
clearInterval(intervalId);
|
|
|
|
// RequestAnimationFrame (for animations)
|
|
function animate() {
|
|
// Animation code
|
|
requestAnimationFrame(animate);
|
|
}
|
|
requestAnimationFrame(animate);
|
|
```
|
|
|
|
### URL API
|
|
|
|
```javascript
|
|
const url = new URL('https://example.com:8080/path?query=value#hash');
|
|
|
|
url.protocol; // 'https:'
|
|
url.hostname; // 'example.com'
|
|
url.port; // '8080'
|
|
url.pathname; // '/path'
|
|
url.search; // '?query=value'
|
|
url.hash; // '#hash'
|
|
url.href; // Full URL
|
|
|
|
// URL parameters
|
|
url.searchParams.get('query'); // 'value'
|
|
url.searchParams.set('newParam', 'newValue');
|
|
url.searchParams.append('query', 'another');
|
|
url.searchParams.delete('query');
|
|
url.searchParams.has('query'); // true/false
|
|
|
|
// Convert to string
|
|
url.toString(); // Full URL
|
|
```
|
|
|
|
### FormData API
|
|
|
|
```javascript
|
|
// Create FormData from form
|
|
const form = document.querySelector('form');
|
|
const formData = new FormData(form);
|
|
|
|
// Create FormData manually
|
|
const data = new FormData();
|
|
data.append('username', 'john');
|
|
data.append('file', fileInput.files[0]);
|
|
|
|
// Get values
|
|
data.get('username'); // 'john'
|
|
data.getAll('files'); // Array of all 'files' values
|
|
|
|
// Iterate
|
|
for (const [key, value] of data.entries()) {
|
|
console.log(key, value);
|
|
}
|
|
|
|
// Send with fetch
|
|
fetch('/api/upload', {
|
|
method: 'POST',
|
|
body: formData // Don't set Content-Type header
|
|
});
|
|
```
|
|
|
|
### Intersection Observer API
|
|
|
|
Detect when element enters viewport:
|
|
|
|
```javascript
|
|
const observer = new IntersectionObserver((entries) => {
|
|
entries.forEach(entry => {
|
|
if (entry.isIntersecting) {
|
|
console.log('Element is visible');
|
|
entry.target.classList.add('visible');
|
|
}
|
|
});
|
|
}, {
|
|
threshold: 0.5, // 50% visible
|
|
rootMargin: '0px'
|
|
});
|
|
|
|
observer.observe(element);
|
|
observer.unobserve(element);
|
|
observer.disconnect(); // Stop observing all
|
|
```
|
|
|
|
### Mutation Observer API
|
|
|
|
Watch for DOM changes:
|
|
|
|
```javascript
|
|
const observer = new MutationObserver((mutations) => {
|
|
mutations.forEach(mutation => {
|
|
console.log('DOM changed:', mutation.type);
|
|
});
|
|
});
|
|
|
|
observer.observe(element, {
|
|
attributes: true, // Watch attribute changes
|
|
childList: true, // Watch child elements
|
|
subtree: true, // Watch all descendants
|
|
characterData: true // Watch text content
|
|
});
|
|
|
|
observer.disconnect(); // Stop observing
|
|
```
|
|
|
|
### Geolocation API
|
|
|
|
```javascript
|
|
navigator.geolocation.getCurrentPosition(
|
|
(position) => {
|
|
console.log(position.coords.latitude);
|
|
console.log(position.coords.longitude);
|
|
},
|
|
(error) => {
|
|
console.error('Error getting location:', error);
|
|
},
|
|
{
|
|
enableHighAccuracy: true,
|
|
timeout: 5000,
|
|
maximumAge: 0
|
|
}
|
|
);
|
|
|
|
// Watch position (continuous updates)
|
|
const watchId = navigator.geolocation.watchPosition(callback);
|
|
navigator.geolocation.clearWatch(watchId);
|
|
```
|
|
|
|
### Web Workers
|
|
|
|
Run JavaScript in background thread:
|
|
|
|
```javascript
|
|
// Main thread
|
|
const worker = new Worker('worker.js');
|
|
|
|
worker.postMessage({ data: 'Hello' });
|
|
|
|
worker.onmessage = (event) => {
|
|
console.log('From worker:', event.data);
|
|
};
|
|
|
|
worker.onerror = (error) => {
|
|
console.error('Worker error:', error);
|
|
};
|
|
|
|
worker.terminate(); // Stop worker
|
|
|
|
// worker.js
|
|
self.onmessage = (event) => {
|
|
console.log('From main:', event.data);
|
|
self.postMessage({ result: 'Done' });
|
|
};
|
|
```
|
|
|
|
### Canvas API
|
|
|
|
Draw graphics:
|
|
|
|
```javascript
|
|
const canvas = document.querySelector('canvas');
|
|
const ctx = canvas.getContext('2d');
|
|
|
|
// Draw rectangle
|
|
ctx.fillStyle = 'blue';
|
|
ctx.fillRect(10, 10, 100, 50);
|
|
|
|
// Draw circle
|
|
ctx.beginPath();
|
|
ctx.arc(100, 100, 50, 0, Math.PI * 2);
|
|
ctx.fillStyle = 'red';
|
|
ctx.fill();
|
|
|
|
// Draw text
|
|
ctx.font = '20px Arial';
|
|
ctx.fillText('Hello', 10, 50);
|
|
|
|
// Draw image
|
|
const img = new Image();
|
|
img.onload = () => {
|
|
ctx.drawImage(img, 0, 0);
|
|
};
|
|
img.src = 'image.jpg';
|
|
```
|
|
|
|
### IndexedDB
|
|
|
|
Client-side database for large amounts of structured data:
|
|
|
|
```javascript
|
|
// Open database
|
|
const request = indexedDB.open('MyDatabase', 1);
|
|
|
|
request.onerror = () => console.error('Database error');
|
|
|
|
request.onsuccess = (event) => {
|
|
const db = event.target.result;
|
|
// Use database
|
|
};
|
|
|
|
request.onupgradeneeded = (event) => {
|
|
const db = event.target.result;
|
|
const objectStore = db.createObjectStore('users', { keyPath: 'id' });
|
|
objectStore.createIndex('name', 'name', { unique: false });
|
|
};
|
|
|
|
// Add data
|
|
const transaction = db.transaction(['users'], 'readwrite');
|
|
const objectStore = transaction.objectStore('users');
|
|
objectStore.add({ id: 1, name: 'John' });
|
|
|
|
// Get data
|
|
const request = objectStore.get(1);
|
|
request.onsuccess = () => console.log(request.result);
|
|
```
|
|
|
|
## Best Practices
|
|
|
|
### Do's
|
|
- ✅ Use `addEventListener` over inline event handlers
|
|
- ✅ Remove event listeners when no longer needed
|
|
- ✅ Use event delegation for dynamic content
|
|
- ✅ Cache DOM queries in variables
|
|
- ✅ Use `textContent` for plain text (safer than `innerHTML`)
|
|
- ✅ Use DocumentFragment for batch DOM operations
|
|
- ✅ Debounce/throttle scroll and resize handlers
|
|
- ✅ Use `requestAnimationFrame` for animations
|
|
- ✅ Validate and sanitize user input
|
|
|
|
### Don'ts
|
|
- ❌ Use `innerHTML` with untrusted data (XSS risk)
|
|
- ❌ Query DOM repeatedly in loops
|
|
- ❌ Modify DOM in tight loops (batch operations)
|
|
- ❌ Use `document.write()` (deprecated)
|
|
- ❌ Use synchronous XMLHttpRequest
|
|
- ❌ Store sensitive data in localStorage
|
|
- ❌ Ignore error handling in async code
|
|
- ❌ Block main thread with heavy computations
|
|
|
|
## Glossary Terms
|
|
|
|
**Key Terms Covered**:
|
|
- API
|
|
- Application context
|
|
- Beacon
|
|
- Blink
|
|
- Blink element
|
|
- Browser
|
|
- Browsing context
|
|
- Buffer
|
|
- Canvas
|
|
- DOM (Document Object Model)
|
|
- Document environment
|
|
- Event
|
|
- Expando
|
|
- Global object
|
|
- Global scope
|
|
- Hoisting
|
|
- IndexedDB
|
|
- Interpolation
|
|
- Node (DOM)
|
|
- Shadow tree
|
|
- WindowProxy
|
|
- Wrapper
|
|
|
|
## Additional Resources
|
|
|
|
- [MDN DOM Reference](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model)
|
|
- [MDN Web APIs](https://developer.mozilla.org/en-US/docs/Web/API)
|
|
- [JavaScript.info DOM](https://javascript.info/document)
|