javascript
examples
examples.js⚡javascript
/**
* Advanced DOM Traversal - Examples
* Powerful techniques for navigating the DOM
*
* Note: These examples are designed for browser environments.
* In Node.js, DOM APIs are not available natively.
*/
// =============================================================================
// 1. TREEWALKER BASICS
// =============================================================================
console.log('--- TreeWalker Basics ---');
// Simulating DOM structure for demonstration
const mockDOM = {
description: `
<div id="root">
<header>
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
</nav>
</header>
<main>
<article>
<h1>Title</h1>
<p>Paragraph 1</p>
<p>Paragraph 2</p>
</article>
</main>
<footer>Copyright 2024</footer>
</div>
`,
};
console.log('DOM Structure:', mockDOM.description);
// TreeWalker usage (browser code):
const treeWalkerExample = `
// Create TreeWalker for elements only
const walker = document.createTreeWalker(
document.body,
NodeFilter.SHOW_ELEMENT,
null // No custom filter
);
// Traverse all elements
const elements = [];
while (walker.nextNode()) {
elements.push(walker.currentNode.tagName);
}
console.log(elements);
`;
console.log('TreeWalker Example Code:');
console.log(treeWalkerExample);
// =============================================================================
// 2. CUSTOM NODE FILTERS
// =============================================================================
console.log('\n--- Custom Node Filters ---');
// NodeFilter result constants
const NodeFilterResults = {
FILTER_ACCEPT: 1, // Accept node
FILTER_REJECT: 2, // Reject node and its children
FILTER_SKIP: 3, // Skip node but process children
};
// Custom filter function
function createFilter(options = {}) {
return {
acceptNode(node) {
// Filter by tag name
if (options.tagNames && !options.tagNames.includes(node.tagName)) {
return NodeFilterResults.FILTER_SKIP;
}
// Filter by class
if (options.className && !node.classList?.contains(options.className)) {
return NodeFilterResults.FILTER_SKIP;
}
// Filter by attribute
if (options.attribute && !node.hasAttribute?.(options.attribute)) {
return NodeFilterResults.FILTER_SKIP;
}
return NodeFilterResults.FILTER_ACCEPT;
},
};
}
console.log('Custom filter example:');
console.log(`
const filter = createFilter({
tagNames: ['DIV', 'SPAN'],
className: 'interactive'
});
const walker = document.createTreeWalker(
document.body,
NodeFilter.SHOW_ELEMENT,
filter
);
`);
// =============================================================================
// 3. NODE ITERATOR
// =============================================================================
console.log('\n--- NodeIterator ---');
// NodeIterator is similar to TreeWalker but simpler
const nodeIteratorExample = `
// NodeIterator for text nodes
const iterator = document.createNodeIterator(
document.body,
NodeFilter.SHOW_TEXT,
{
acceptNode(node) {
// Only accept non-empty text
return node.textContent.trim()
? NodeFilter.FILTER_ACCEPT
: NodeFilter.FILTER_REJECT;
}
}
);
// Collect all text content
const textNodes = [];
let node;
while ((node = iterator.nextNode())) {
textNodes.push(node.textContent.trim());
}
`;
console.log('NodeIterator Example:', nodeIteratorExample);
// =============================================================================
// 4. RANGE API
// =============================================================================
console.log('\n--- Range API ---');
// Range represents a fragment of a document
const rangeExample = `
// Create a range
const range = document.createRange();
// Select entire contents of an element
range.selectNodeContents(element);
// Select specific portion
range.setStart(startNode, startOffset);
range.setEnd(endNode, endOffset);
// Range properties
console.log({
startContainer: range.startContainer,
startOffset: range.startOffset,
endContainer: range.endContainer,
endOffset: range.endOffset,
collapsed: range.collapsed,
commonAncestorContainer: range.commonAncestorContainer
});
// Range manipulation
const contents = range.extractContents(); // Remove and return
const clone = range.cloneContents(); // Clone without removing
range.deleteContents(); // Just delete
range.insertNode(newNode); // Insert at start
range.surroundContents(wrapper); // Wrap contents
`;
console.log('Range API Example:', rangeExample);
// =============================================================================
// 5. SELECTION API
// =============================================================================
console.log('\n--- Selection API ---');
const selectionExample = `
// Get the selection object
const selection = window.getSelection();
// Selection properties
console.log({
anchorNode: selection.anchorNode, // Where selection started
anchorOffset: selection.anchorOffset,
focusNode: selection.focusNode, // Where selection ended
focusOffset: selection.focusOffset,
isCollapsed: selection.isCollapsed, // Is it a cursor?
rangeCount: selection.rangeCount,
type: selection.type // 'Caret', 'Range', 'None'
});
// Get selected text
const selectedText = selection.toString();
// Work with ranges
if (selection.rangeCount > 0) {
const range = selection.getRangeAt(0);
// Manipulate range...
}
// Modify selection
selection.removeAllRanges(); // Clear selection
selection.addRange(range); // Set new selection
// Collapse selection
selection.collapse(node, offset);
// Select all in element
selection.selectAllChildren(element);
`;
console.log('Selection API Example:', selectionExample);
// =============================================================================
// 6. FINDING TEXT IN DOM
// =============================================================================
console.log('\n--- Finding Text in DOM ---');
function findTextExample() {
return `
// Find all text nodes containing a string
function findTextContaining(searchText, rootElement = document.body) {
const matches = [];
const walker = document.createTreeWalker(
rootElement,
NodeFilter.SHOW_TEXT,
{
acceptNode(node) {
return node.textContent.toLowerCase()
.includes(searchText.toLowerCase())
? NodeFilter.FILTER_ACCEPT
: NodeFilter.FILTER_REJECT;
}
}
);
while (walker.nextNode()) {
matches.push({
node: walker.currentNode,
parent: walker.currentNode.parentElement,
text: walker.currentNode.textContent
});
}
return matches;
}
// Usage
const results = findTextContaining('search term');
results.forEach(result => {
result.parent.classList.add('highlight');
});
`;
}
console.log(findTextExample());
// =============================================================================
// 7. HIGHLIGHT TEXT
// =============================================================================
console.log('\n--- Text Highlighting ---');
const highlightExample = `
// Highlight all occurrences of text
function highlightText(searchText, className = 'highlight') {
const textNodes = findTextContaining(searchText);
textNodes.forEach(({ node }) => {
const text = node.textContent;
const regex = new RegExp('(' + escapeRegex(searchText) + ')', 'gi');
const wrapper = document.createElement('span');
wrapper.innerHTML = text.replace(regex, '<mark class="' + className + '">$1</mark>');
node.parentNode.replaceChild(wrapper, node);
});
}
function escapeRegex(string) {
return string.replace(/[.*+?^\${}()|[\\]\\\\]/g, '\\\\$&');
}
// Remove highlights
function removeHighlights(className = 'highlight') {
document.querySelectorAll('mark.' + className).forEach(mark => {
const parent = mark.parentNode;
parent.replaceChild(document.createTextNode(mark.textContent), mark);
parent.normalize(); // Merge adjacent text nodes
});
}
`;
console.log('Text Highlighting:', highlightExample);
// =============================================================================
// 8. CUSTOM ELEMENT QUERIES
// =============================================================================
console.log('\n--- Custom Element Queries ---');
// Collection of custom query utilities
const customQueries = {
// Find elements by computed style
findByComputedStyle: `
function findByComputedStyle(property, value, root = document) {
const elements = root.querySelectorAll('*');
const matches = [];
elements.forEach(el => {
const computed = getComputedStyle(el);
if (computed[property] === value) {
matches.push(el);
}
});
return matches;
}
// Find all visible elements
const visibleElements = findByComputedStyle('display', 'block');
// Find all fixed elements
const fixedElements = findByComputedStyle('position', 'fixed');
`,
// Find by bounding rect
findInViewport: `
function findInViewport(root = document.body) {
const elements = root.querySelectorAll('*');
const viewport = {
top: 0,
left: 0,
bottom: window.innerHeight,
right: window.innerWidth
};
return Array.from(elements).filter(el => {
const rect = el.getBoundingClientRect();
return (
rect.top < viewport.bottom &&
rect.bottom > viewport.top &&
rect.left < viewport.right &&
rect.right > viewport.left
);
});
}
`,
// Find by data attribute pattern
findByDataPattern: `
function findByDataPattern(pattern, root = document) {
const elements = root.querySelectorAll('*');
const regex = new RegExp(pattern);
return Array.from(elements).filter(el => {
return Array.from(el.attributes).some(attr =>
attr.name.startsWith('data-') && regex.test(attr.value)
);
});
}
`,
};
console.log('Custom Query Examples:');
Object.entries(customQueries).forEach(([name, code]) => {
console.log(`\n${name}:`);
console.log(code);
});
// =============================================================================
// 9. SHADOW DOM TRAVERSAL
// =============================================================================
console.log('\n--- Shadow DOM ---');
const shadowDOMExample = `
// Creating Shadow DOM
class MyComponent extends HTMLElement {
constructor() {
super();
// Attach shadow root
this.attachShadow({ mode: 'open' });
// Add content to shadow root
this.shadowRoot.innerHTML = \`
<style>
.internal { color: blue; }
</style>
<div class="internal">
Shadow DOM content
</div>
\`;
}
}
customElements.define('my-component', MyComponent);
// Traversing Shadow DOM
function traverseShadowDOM(root) {
const walker = document.createTreeWalker(
root,
NodeFilter.SHOW_ELEMENT,
null
);
const elements = [];
while (walker.nextNode()) {
const node = walker.currentNode;
elements.push(node);
// Check for shadow root
if (node.shadowRoot) {
elements.push(...traverseShadowDOM(node.shadowRoot));
}
}
return elements;
}
// Find element across shadow boundaries
function deepQuerySelector(selector, root = document) {
let element = root.querySelector(selector);
if (element) return element;
// Search in shadow roots
const walker = document.createTreeWalker(
root,
NodeFilter.SHOW_ELEMENT,
null
);
while (walker.nextNode()) {
if (walker.currentNode.shadowRoot) {
element = deepQuerySelector(selector, walker.currentNode.shadowRoot);
if (element) return element;
}
}
return null;
}
`;
console.log('Shadow DOM Traversal:', shadowDOMExample);
// =============================================================================
// 10. DOM UTILITIES CLASS
// =============================================================================
console.log('\n--- DOM Utilities Class ---');
const domUtilitiesCode = `
class DOMUtils {
// Find all elements matching multiple selectors
static findMultiple(...selectors) {
return selectors.flatMap(selector =>
Array.from(document.querySelectorAll(selector))
);
}
// Get element's path from root
static getPath(element) {
const path = [];
while (element && element !== document.documentElement) {
let selector = element.tagName.toLowerCase();
if (element.id) {
selector += '#' + element.id;
} else if (element.className) {
selector += '.' + element.className.split(' ').join('.');
}
path.unshift(selector);
element = element.parentElement;
}
return path.join(' > ');
}
// Find common ancestor
static commonAncestor(el1, el2) {
const ancestors = new Set();
let current = el1;
while (current) {
ancestors.add(current);
current = current.parentElement;
}
current = el2;
while (current) {
if (ancestors.has(current)) {
return current;
}
current = current.parentElement;
}
return null;
}
// Get all siblings
static siblings(element, filter = null) {
return Array.from(element.parentElement.children)
.filter(child => child !== element)
.filter(child => filter ? filter(child) : true);
}
// Find next/previous matching sibling
static nextMatching(element, selector) {
let sibling = element.nextElementSibling;
while (sibling) {
if (sibling.matches(selector)) return sibling;
sibling = sibling.nextElementSibling;
}
return null;
}
// Check if element is ancestor
static isAncestor(ancestor, descendant) {
let current = descendant.parentElement;
while (current) {
if (current === ancestor) return true;
current = current.parentElement;
}
return false;
}
}
`;
console.log('DOM Utilities Class:', domUtilitiesCode);
console.log('\n=== Advanced DOM Traversal examples loaded. ===');
console.log('These examples require a browser environment to run.');