JavaScript & Frontend Cheatsheet for Architects
· 1 year ago
cf33d3f6a7773ae46f019d0c9b83374ea596ba6b
Parent:
548c806c2
1 file changed +2017 −0
- javascript-for-architects.html +2017 −0
Diff
--- /dev/null +++ b/javascript-for-architects.html @@ -0,0 +1,2017 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Interactive JavaScript & Frontend Cheatsheet: Modern JS, React, & Ecosystem Guide for Architects</title> + + <link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>📜</text></svg>"> + + <!-- SEO Meta Description --> + <meta name="description" content="Comprehensive interactive cheatsheet for modern JavaScript (ES6+), frontend frameworks (React, Vue, Angular, Svelte), Web APIs, tooling (Vite, Webpack), and architectural patterns for developers and architects."> + <!-- Keywords --> + <meta name="keywords" content="JavaScript, ES6, React, Vue, Angular, Svelte, Frontend, Cheatsheet, Web APIs, DOM, Fetch, Promises, Async/Await, Hooks, Context API, Redux, Vite, Webpack, Node.js, TypeScript, HTML, CSS, Developer Guide, Programming, Architecture"> + + <!-- Canonical URL --> + <link rel="canonical" href="https://cheatsheets.davidveksler.com/javascript-for-architects.html"> + + <!-- Social Media Metadata (Open Graph) --> + <meta property="og:title" content="Interactive JavaScript & Frontend Cheatsheet: Modern JS, React, & Ecosystem Guide for Architects"> + <meta property="og:description" content="Explore modern JavaScript (ES6+), React hooks, other major frameworks (Vue, Angular, Svelte), Web APIs, essential tooling, state management, and architectural insights."> + <meta property="og:type" content="article"> + <meta property="og:url" content="https://cheatsheets.davidveksler.com/javascript-for-architects.html"> + <meta property="og:image" content="https://cheatsheets.davidveksler.com/images/javascript-cheatsheet-architects.png"> <!-- UPDATE IMAGE PATH --> + <meta property="og:image:alt" content="Visual diagram connecting JavaScript core features, React concepts, Vue, Angular, Svelte, Web APIs, and frontend tooling for architects."> + <meta property="og:site_name" content="David Veksler Cheatsheets"> + <meta property="article:published_time" content="2024-01-20T09:00:00Z"> + <meta property="article:modified_time" content="2025-05-12T10:00:00Z"> <!-- Update Last Modified --> + <meta property="article:author" content="https://www.linkedin.com/in/davidveksler/"> + + + <!-- Twitter Card Metadata --> + <meta name="twitter:card" content="summary_large_image"> + <meta name="twitter:title" content="Interactive JavaScript & Frontend Cheatsheet: Modern JS, React, & Ecosystem Guide for Architects"> + <meta name="twitter:description" content="Your go-to interactive guide for modern JavaScript, React, Vue, Angular, Svelte, frontend frameworks, Web APIs, and the essential tooling ecosystem."> + <meta name="twitter:image" content="https://cheatsheets.davidveksler.com/images/javascript-cheatsheet-architects.png"> <!-- UPDATE IMAGE PATH --> + <meta name="twitter:image:alt" content="Overview of the JavaScript ecosystem including ES6+, React, Vue, Angular, Svelte, DOM APIs, and build tools."> + <!-- Optional: <meta name="twitter:site" content="@DavidVekslerTwitter"> --> + <!-- Optional: <meta name="twitter:creator" content="@DavidVekslerTwitter"> --> + + <!-- Structured Data (JSON-LD) --> + <script type="application/ld+json"> + { + "@context": "https://schema.org", + "@type": "TechArticle", + "headline": "Interactive JavaScript & Frontend Cheatsheet - Modern JS (ES6+), React, Vue, Angular, Svelte, Web APIs, Tooling for Architects", + "description": "A comprehensive interactive cheatsheet covering modern JavaScript features (ES6+), frontend development with React, Vue, Angular, Svelte, Web APIs (DOM, Fetch), essential tooling (Vite, Webpack, npm), state management, and architectural best practices for developers and architects.", + "image": "https://cheatsheets.davidveksler.com/images/javascript-cheatsheet-architects.png", + "author": { + "@type": "Person", + "name": "David Veksler", + "url": "https://www.linkedin.com/in/davidveksler/" + }, + "publisher": { + "@type": "Organization", + "name": "David Veksler Cheatsheets", + "logo": { + "@type": "ImageObject", + "url": "https://cheatsheets.davidveksler.com/images/logo-placeholder.png" // UPDATE LOGO PATH + } + }, + "datePublished": "2024-01-20T09:00:00Z", + "dateModified": "2025-05-12T10:00:00Z", // Update Last Modified + "mainEntityOfPage": { + "@type": "WebPage", + "@id": "https://cheatsheets.davidveksler.com/javascript-for-architects.html" + }, + "keywords": "JavaScript, ES6, React, Vue, Angular, Svelte, Frontend, Cheatsheet, Web APIs, DOM, Fetch, Promises, Async/Await, Hooks, Context API, Redux, Vite, Webpack, Node.js, TypeScript, HTML, CSS, Developer Guide, Programming, Architecture, State Management, Testing, Tooling" + } + </script> + + <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"> + <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.min.css"> + <script src="https://cdn.jsdelivr.net/npm/[email protected]/leader-line.min.js"></script> + <!-- Optional: Add Prism.js for code highlighting --> + <!-- <link href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism-okaidia.min.css" rel="stylesheet" /> --> + <!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-core.min.js"></script> --> + <!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/autoloader/prism-autoloader.min.js"></script> --> + + + <style> + :root { + --bs-body-bg: #f0f4f8; /* Lighter, slightly blueish background */ + --bs-primary: #6F42C1; /* A neutral purple as primary action color */ + --bs-primary-dark: #5a349b; + --bs-primary-light: #e2d9f3; + --card-border-color: #adb5bd; + --card-shadow-color: rgba(0, 30, 80, .1); + --text-color-main: #212529; + --text-color-secondary: #495057; + --text-color-highlight: var(--bs-primary-dark); + --blueprint-grid-color: rgba(108, 117, 125, 0.1); /* Subtler grid */ + --schema-bg-color: rgba(255, 255, 255, 0.7); + --schema-border-color: #beb3e4; /* Lighter purple for schema borders */ + + /* --- JS Category Colors --- */ + --js-color-core: #F7DF1E; /* JS Yellow */ + --js-color-modern: #007ACC; /* Bright Blue */ + --js-color-browser: #4CAF50; /* Green */ + --js-color-frameworks: #61DAFB; /* React Blue (Default for section) */ + --js-color-state: #9C27B0; /* Purple */ + --js-color-tooling: #6c757d; /* Gray */ + --js-color-advanced: #FFC107; /* Amber */ + --js-color-arch: #4A4A4A; /* Dark Gray */ + + /* Framework specific overrides */ + --js-color-react: #61DAFB; + --js-color-vue: #42b883; + --js-color-angular: #DD0031; + --js-color-svelte: #FF3E00; + + + --db-category-color: var(--js-color-tooling); /* Default category color */ + } + + @keyframes blueprintGridAnimation { + 0% { background-position: 0 0, 0 0; } + 100% { background-position: 60px 60px, -60px -60px; } + } + + body { + background-color: var(--bs-body-bg); + background-image: + linear-gradient(to right, var(--blueprint-grid-color) 1px, transparent 1px), + linear-gradient(to bottom, var(--blueprint-grid-color) 1px, transparent 1px); + background-size: 60px 60px; + animation: blueprintGridAnimation 90s linear infinite; + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + padding-bottom: 3rem; + font-size: 16px; + color: var(--text-color-main); + box-sizing: border-box; + } + *, *::before, *::after { box-sizing: inherit; } + + .page-header { + /* A slightly different gradient, maybe leaning towards JS yellow/blue */ + background: linear-gradient(135deg, #f0e8c0, #cde7f8); + padding: 2.5rem 1.5rem; + text-align: center; + border-bottom: 2px solid var(--schema-border-color); + margin-bottom: 1.5rem; + position: relative; + z-index: 10; + box-shadow: 0 4px 15px rgba(100, 100, 100, 0.1); + } + .page-header h1 { + color: #333; /* Darker text for contrast on light bg */ + font-weight: 300; + letter-spacing: 0.5px; + margin-bottom: 0.5rem; + font-size: 2.8rem; + } + .page-header h1 .bi { font-size: 0.9em; vertical-align: -0.05em; margin-right: 0.3em; color: var(--js-color-core); } + .page-header .lead { color: #495057; font-size: 1.15rem; max-width: 800px; margin: auto; } + + #filter-controls { + background-color: rgba(255, 255, 255, 0.85); + backdrop-filter: blur(5px); + padding: 1rem; + border-radius: 8px; + box-shadow: 0 2px 10px rgba(0,0,0,0.07); + margin-bottom: 2rem; + position: sticky; + top: 10px; + z-index: 100; + } + + #category-filters .btn { + margin: 0.25rem; + font-size: 0.9rem; + } + #category-filters .btn.active { + background-color: var(--bs-primary); /* Use primary action color */ + color: white; + border-color: var(--bs-primary-dark); + } + #search-box { + border-color: var(--schema-border-color); + } + #search-box:focus { + border-color: var(--bs-primary); + box-shadow: 0 0 0 0.25rem rgba(111, 66, 193, 0.25); /* Primary action color focus */ + } + + .schema-container { + background-color: var(--schema-bg-color); + border: 2px solid var(--schema-border-color); + border-radius: 8px; + padding: 1.5rem 1.5rem 0.5rem 1.5rem; + margin-bottom: 2.5rem; + box-shadow: 0 5px 15px rgba(111, 66, 193, 0.07); /* Primary action color shadow */ + backdrop-filter: blur(4px); + position: relative; + transition: opacity 0.3s ease-in-out; + } + + .section-title { + color: var(--db-category-color); /* Uses the section's category color */ + margin: -2.8rem 0 1.5rem 0; + font-weight: 600; + text-transform: uppercase; + letter-spacing: .08em; + font-size: 1.1rem; + border-bottom: none; + padding: 0.4rem 1rem; + background-color: var(--bs-body-bg); + display: inline-block; + position: relative; + left: 1rem; + z-index: 15; + border: 2px solid var(--schema-border-color); + border-bottom: none; + border-radius: 6px 6px 0 0; + transition: opacity 0.3s ease-in-out; + } + + .info-card { + background: #fff; + border: 1px solid var(--card-border-color); + border-radius: 4px; + box-shadow: 0 3px 8px var(--card-shadow-color); + height: 100%; + display: flex; + flex-direction: column; + transition: box-shadow 0.3s ease, opacity 0.3s ease, transform 0.2s ease; + position: relative; + z-index: 5; + opacity: 1; + } + + .info-card.is-highlighted { + transform: scale(1.01); + box-shadow: 0 0 0 3px var(--db-category-color), 0 8px 16px rgba(0, 50, 130, .2) !important; + z-index: 25 !important; + } + .info-card:not(.is-highlighted):hover { + box-shadow: 0 5px 12px rgba(0, 60, 150, .18); + transform: translateY(-2px); + z-index: 20; + } + + .info-card .card-body { padding: 0; flex-grow: 1; display: flex; flex-direction: column; } + .info-card h5 { + color: #fff; /* White text often looks good on colored bg */ + background-color: var(--db-category-color); /* Uses card's specific color */ + font-size: 1rem; text-align: center; margin: 0; padding: 0.7rem 0.5rem; + font-weight: 600; display: flex; justify-content: center; align-items: center; + gap: .5rem; font-family: 'Segoe UI Semibold', Consolas, Menlo, Monaco, 'Courier New', monospace; + border-bottom: 1px solid var(--card-border-color); + border-radius: 3px 3px 0 0; + position: relative; + } + /* Adjust icon color if needed based on bg */ + .info-card h5 .bi { font-size: 1.2em; opacity: 0.9; } + /* Special handling for yellow/light bg text */ + .card-core h5, .card-advanced h5, .card-svelte h5 { color: #333; } /* Darker text on yellow/orange */ + .card-core h5 .bi, .card-advanced h5 .bi, .card-svelte h5 .bi { color: #333; } + + + .version-tag { + font-size: 0.65rem; + font-weight: normal; + background-color: rgba(0,0,0,0.2); + color: #fff; /* White text generally ok */ + padding: 0.1em 0.4em; + border-radius: 3px; + margin-left: 0.5em; + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + } + /* Adjust version tag text color for light backgrounds */ + .card-core .version-tag, .card-advanced .version-tag, .card-svelte .version-tag, + .card-frameworks .version-tag { /* Make default framework tag also dark text friendly */ + background-color: rgba(0,0,0,0.1); color: #333; + } + + + .card-content-wrapper { padding: 1rem; flex-grow: 1; display: flex; flex-direction: column; } + .info-card p.summary { font-size: .9rem; color: var(--text-color-secondary); margin-bottom: .8rem; flex-grow: 1; line-height: 1.6; } + + .collapse-content { font-size: 0.9rem; border-top: 1px solid #e9ecef; padding-top: 1rem; margin-top: 1rem; color: var(--text-color-main); } + .collapse-content h6 { font-weight: 700; color: var(--text-color-highlight); margin-top: 0.8rem; margin-bottom: 0.3rem; font-size: 0.95rem; } + .collapse-content ul { padding-left: 0.5rem; margin-bottom: 0.8rem; list-style: none; } + .collapse-content li { margin-bottom: 0.6rem; padding-bottom: 0.6rem; font-size: 0.88rem; line-height: 1.5; border-bottom: 1px dotted #ced4da; position: relative; padding-left: 1.6rem; } + .collapse-content li:last-child { border-bottom: none; margin-bottom: 0; } + .collapse-content li::before { + /* Using a JS-like icon */ + content: "\F43D"; /* Bootstrap icon: braces */ + font-family: "bootstrap-icons"; position: absolute; left: 0; top: 2px; + color: var(--db-category-color); opacity: 0.7; font-size: 1em; + } + .collapse-content li strong { color: var(--text-color-highlight); display: block; margin-bottom: 0.2rem; font-weight: 600; } + .collapse-content p { font-size: 0.9rem; margin-bottom: 0.6rem; line-height: 1.55; } + .collapse-content code { font-size: 0.85rem; color: #c2185b; background-color: #f8f9fa; padding: 0.2em 0.4em; border-radius: 3px; font-family: Consolas, Menlo, Monaco, 'Courier New', monospace; border: 1px solid #eee;} + .collapse-content pre { background-color: #f8f9fa; border: 1px solid #eee; padding: 0.8rem; border-radius: 4px; font-size: 0.85rem; overflow-x: auto;} + .collapse-content pre code { background-color: transparent; border: none; padding: 0; } + + + .row > * { margin-bottom: 2rem; } + footer { padding-top: 3rem; font-size: .85em; color: #6c757d; position: relative; z-index: 10; text-align: center; } + + .details-toggle { + font-size: 0.8rem; margin-top: auto; align-self: flex-start; + padding: 0.3rem 0.6rem; color: var(--db-category-color); + border: 1px solid var(--db-category-color); background-color: transparent; + transition: background-color 0.2s ease, color 0.2s ease; + display: inline-flex; align-items: center; gap: 0.3em; + border-radius: 3px; + } + .details-toggle:hover { background-color: var(--db-category-color); color: white; } + /* Adjust hover text color for light bg toggles */ + .card-core .details-toggle:hover, + .card-advanced .details-toggle:hover, + .card-svelte .details-toggle:hover { color: #333; } + + + .details-toggle .bi { transition: transform 0.2s ease-in-out; } + .details-toggle[aria-expanded="true"] .bi { transform: rotate(180deg); } + + .term { font-weight: 600; color: var(--bs-primary-dark); background-color: var(--bs-primary-light); padding: 0.1em 0.35em; border-radius: 3px; cursor: help;} + a { color: var(--bs-primary); text-decoration: none; } + a:hover { color: var(--bs-primary-dark); text-decoration: underline; } + .collapse-content a { color: #583cb3; } /* Slightly darker purple link */ + .collapse-content a:hover { color: #463090; } + + .leader-line { pointer-events: none; z-index: 20; transition: opacity 0.3s ease-in-out; } + + /* --- JS Category Color Styling --- */ + .section-core, .card-core { --db-category-color: var(--js-color-core); } + .section-modern, .card-modern { --db-category-color: var(--js-color-modern); } + .section-browser, .card-browser { --db-category-color: var(--js-color-browser); } + .section-frameworks /* Default section title color */ { --db-category-color: var(--js-color-frameworks); } + .section-state, .card-state { --db-category-color: var(--js-color-state); } + .section-tooling, .card-tooling { --db-category-color: var(--js-color-tooling); } + .section-advanced, .card-advanced { --db-category-color: var(--js-color-advanced); } + .section-arch, .card-arch { --db-category-color: var(--js-color-arch); } + + /* Framework specific card overrides */ + .card-react { --db-category-color: var(--js-color-react); } + .card-vue { --db-category-color: var(--js-color-vue); } + .card-angular { --db-category-color: var(--js-color-angular); } + .card-svelte { --db-category-color: var(--js-color-svelte); } + + </style> +</head> +<body> +<header class="page-header"> + <h1><i class="bi bi-braces" aria-hidden="true" data-bs-toggle="tooltip" data-bs-placement="bottom" title="JavaScript Icon"></i> JavaScript & Frontend Cheatsheet for Architects</h1> + <p class="lead">An interactive guide to modern JavaScript (ES6+), frontend frameworks (React, Vue, Angular, Svelte), Web APIs, tooling, and architectural best practices.</p> +</header> + +<div class="container"> + <div id="filter-controls" class="mb-4"> + <input type="search" id="search-box" class="form-control mb-3" placeholder="Search topics, features, keywords (e.g., 'useState', 'fetch', 'webpack')..." data-bs-toggle="tooltip" data-bs-placement="bottom" title="Type to search for topics, features, or keywords within the cheatsheet."> + <div id="category-filters" class="btn-toolbar" role="toolbar" aria-label="Category Filters" data-bs-toggle="tooltip" data-bs-placement="top" title="Filter the cheatsheet content by category."> + <!-- Filter buttons will be injected here by JavaScript --> + </div> + <div id="no-results" class="alert alert-warning mt-3" style="display: none;">No items match your criteria. Try refining your search or selecting a different category.</div> + </div> +</div> + +<div class="container" id="main-container"> + + <!-- I. JavaScript Core Fundamentals --> + <div class="schema-container section-core" data-section-id="section-core" data-section-name="JS Core"> + <h2 class="section-title" id="section-core-title">JavaScript Core Fundamentals</h2> + <div class="row"> + <div class="col-lg-4 col-md-6"> + <div class="info-card card-core" id="card-js-overview"> + <div class="card-body"> + <h5><i class="bi bi-code-slash" aria-hidden="true" data-bs-toggle="tooltip" data-bs-placement="top" title="Code Icon"></i> JS Overview</h5> + <div class="card-content-wrapper"> + <p class="summary">A high-level, <span class="term" data-bs-toggle="tooltip" title="Types are checked during runtime, not compile time.">dynamically typed</span>, <span class="term" data-bs-toggle="tooltip" title="Code is executed line by line on a single main thread.">single-threaded</span> language primarily used for web development (browsers, Node.js). <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/About" target="_blank" rel="noopener noreferrer" data-bs-toggle="tooltip" title="External link: MDN About JavaScript">MDN Intro</a></p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseJsOverview" aria-expanded="false" aria-controls="collapseJsOverview"> + Details <i class="bi bi-chevron-down" aria-hidden="true"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseJsOverview"> + <h6>Purpose</h6> + <p>Adds interactivity to web pages, builds web/mobile apps, powers servers (Node.js), and more.</p> + <h6>Key Characteristics</h6> + <ul> + <li><strong>Dynamic Typing:</strong> Variable types are determined at runtime.</li> + <li><strong>Interpreted:</strong> Typically executed directly by an engine (e.g., V8, SpiderMonkey) without explicit compilation step for distribution.</li> + <li><strong>Event Loop:</strong> Handles asynchronous operations non-blockingly despite being single-threaded. <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop" target="_blank" rel="noopener noreferrer">Event Loop</a></li> + <li><strong>Prototype-based Inheritance:</strong> Objects inherit directly from other objects.</li> + </ul> + <!-- Detailed content needed --> + </div> + </div> + </div> + <div class="col-lg-4 col-md-6"> + <div class="info-card card-core" id="card-js-vars"> + <div class="card-body"> + <h5><i class="bi bi-bounding-box-circles" aria-hidden="true" data-bs-toggle="tooltip" data-bs-placement="top" title="Scope Icon"></i> Variables & Scope</h5> + <div class="card-content-wrapper"> + <p class="summary">Declare variables using <span class="term" data-bs-toggle="tooltip" title="Modern block-scoped variable declaration."><code>let</code></span>, <span class="term" data-bs-toggle="tooltip" title="Modern block-scoped constant declaration (cannot be reassigned)."><code>const</code></span> (preferred), or legacy <span class="term" data-bs-toggle="tooltip" title="Older function-scoped variable declaration (avoid in modern JS)."><code>var</code></span>. Understand block vs. function scope. <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Grammar_and_types#Declarations" target="_blank" rel="noopener noreferrer">MDN Declarations</a></p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseJsVars" aria-expanded="false" aria-controls="collapseJsVars"> + Details <i class="bi bi-chevron-down" aria-hidden="true"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseJsVars"> + <h6>Declarations</h6> + <ul> + <li><strong><code>const</code>:</strong> Block-scoped. Must be initialized. Cannot be reassigned. (Object/array contents *can* be mutated).</li> + <li><strong><code>let</code>:</strong> Block-scoped. Can be reassigned. Can be declared without initialization.</li> + <li><strong><code>var</code>:</strong> Function-scoped (or global). Subject to hoisting issues. Avoid in modern code.</li> + </ul> + <h6>Scope</h6> + <ul> + <li><strong>Block Scope:</strong> Variables declared with `let` or `const` inside `{...}` blocks (like `if`, `for`) are only accessible within that block.</li> + <li><strong>Function Scope:</strong> Variables declared with `var` are accessible anywhere within the function they are defined in.</li> + <li><strong>Global Scope:</strong> Variables declared outside any function/block.</li> + </ul> + <h6>Hoisting</h6> + <p><code>var</code> declarations are conceptually "moved" to the top of their scope, but initializations are not. `let` and `const` are hoisted but not initialized (Temporal Dead Zone). Accessing them before declaration throws an error. <a href="https://developer.mozilla.org/en-US/docs/Glossary/Hoisting" target="_blank">Hoisting</a></p> + <pre><code class="language-javascript">// Example +if (true) { + let blockVar = "I'm block scoped"; + const blockConst = "Me too!"; + var funcVar = "I'm function scoped!"; // if this 'if' is in global, funcVar is global +} +console.log(typeof blockVar); // undefined (ReferenceError if accessed directly) +// console.log(blockConst); // ReferenceError +// console.log(funcVar); // "I'm function scoped!" (if 'if' block was global) + +function testScope() { + if (true) { var funcVarInner = "Inner func scope"; } + // console.log(funcVarInner); // "Inner func scope" +} +// console.log(typeof funcVarInner); // undefined (ReferenceError) +</code></pre> + </div> + </div> + </div> + <div class="col-lg-4 col-md-6"> + <div class="info-card card-core" id="card-js-types"> + <div class="card-body"> + <h5><i class="bi bi-tags" aria-hidden="true" data-bs-toggle="tooltip" data-bs-placement="top" title="Data Types Icon"></i> Data Types</h5> + <div class="card-content-wrapper"> + <p class="summary">JS has <span class="term" data-bs-toggle="tooltip" title="string, number, boolean, null, undefined, symbol, bigint">primitive types</span> and the <span class="term" data-bs-toggle="tooltip" title="Collections of key-value pairs, including arrays and functions.">Object</span> type. Beware of <span class="term" data-bs-toggle="tooltip" title="Automatic conversion between types (e.g., '5' + 1 = '51').">type coercion</span>. Use `typeof` operator. <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures" target="_blank" rel="noopener noreferrer">MDN Data Structures</a></p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseJsTypes" aria-expanded="false" aria-controls="collapseJsTypes"> + Details <i class="bi bi-chevron-down" aria-hidden="true"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseJsTypes"> + <h6>Primitives (Immutable)</h6> + <ul> + <li><strong>string:</strong> Textual data (e.g., `"hello"`).</li> + <li><strong>number:</strong> Numeric values (e.g., `42`, `3.14`). Includes `Infinity`, `-Infinity`, `NaN`.</li> + <li><strong>boolean:</strong> Logical values (`true`, `false`).</li> + <li><strong>null:</strong> Intentional absence of any object value. (`typeof null` is `"object"` - a historical quirk).</li> + <li><strong>undefined:</strong> Variable declared but not yet assigned a value.</li> + <li><strong>symbol (ES6):</strong> Unique and immutable primitive value, often used as object property keys.</li> + <li><strong>bigint (ES2020):</strong> Arbitrary precision integers (e.g., `9007199254740991n`).</li> + </ul> + <h6>Object (Mutable)</h6> + <ul> + <li><strong>object:</strong> Collection of properties (key-value pairs). Includes arrays, functions, Date, RegExp, etc.</li> + </ul> + <h6>Type Coercion</h6> + <p>JavaScript often implicitly converts types during operations. Use strict equality (`===` and `!==`) to avoid coercion. <a href="https://developer.mozilla.org/en-US/docs/Glossary/Type_coercion" target="_blank">Type Coercion</a></p> + <pre><code class="language-javascript">console.log(typeof 42); // "number" +console.log(typeof "hello"); // "string" +console.log(typeof true); // "boolean" +console.log(typeof undefined); // "undefined" +console.log(typeof null); // "object" (quirk) +console.log(typeof {}); // "object" +console.log(typeof []); // "object" (arrays are objects) +console.log(typeof function(){}); // "function" (functions are objects) + +console.log('5' == 5); // true (coercion) +console.log('5' === 5); // false (strict equality)</code></pre> + </div> + </div> + </div> + <div class="col-lg-4 col-md-6"> + <div class="info-card card-core" id="card-js-functions"> + <div class="card-body"> + <h5><i class="bi bi-braces" aria-hidden="true"></i> Functions</h5> + <div class="card-content-wrapper"> + <p class="summary">Reusable blocks of code. Defined using declarations or expressions. Understand scope, <span class="term" data-bs-toggle="tooltip" title="Function remembers its lexical scope even when executed outside that scope.">closures</span>, and the <span class="term" data-bs-toggle="tooltip" title="Execution context, value depends on how the function is called.">`this`</span> keyword. <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions" target="_blank">MDN Functions</a></p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseJsFunc" aria-expanded="false" aria-controls="collapseJsFunc"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseJsFunc"> + <h6>Key Concepts</h6> + <ul> + <li><strong>Declaration:</strong> `function myFunction() { ... }` (Hoisted)</li> + <li><strong>Expression:</strong> `const myFunction = function() { ... };` (Not fully hoisted)</li> + <li><strong>Parameters & Arguments:</strong> Inputs to functions.</li> + <li><strong>Return Value:</strong> Output using `return` keyword (defaults to `undefined`).</li> + <li><strong>Closures:</strong> A function bundled with references to its surrounding state (lexical environment). Allows accessing outer scope variables even after the outer function has finished. <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures" target="_blank">Closures</a></li> + <li><strong>`this` Keyword:</strong> Context object. Behavior depends on invocation: global object (sloppy mode), `undefined` (strict mode), object in method calls, new instance with `new`, explicitly set via `call`/`apply`/`bind`. Arrow functions inherit `this` lexically. <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this" target="_blank">`this` Keyword</a></li> + <li><strong>Default Parameters (ES6):</strong> `function greet(name = 'Guest') { ... }`</li> + <li><strong>Rest Parameters (ES6):</strong> `function sum(...numbers) { ... }` (collects remaining arguments into an array)</li> + </ul> + <p><em>More examples on 'this' and closures needed here.</em></p> + </div> + </div> + </div> + <div class="col-lg-4 col-md-6"> + <div class="info-card card-core" id="card-js-arrays"> + <div class="card-body"> + <h5><i class="bi bi-list-ol" aria-hidden="true"></i> Arrays</h5> + <div class="card-content-wrapper"> + <p class="summary">Ordered lists of values. Access elements via index. Rich set of built-in methods for iteration, mutation, etc. Use <span class="term" data-bs-toggle="tooltip" title="Syntax like ...myArray to expand array elements.">spread syntax (`...`)</span>. <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array" target="_blank">MDN Array</a></p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseJsArr" aria-expanded="false" aria-controls="collapseJsArr"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseJsArr"> + <h6>Common Methods</h6> + <ul> + <li><strong>Iteration:</strong> `forEach()`, `map()`, `filter()`, `reduce()`, `find()`, `findIndex()`, `some()`, `every()`</li> + <li><strong>Mutation:</strong> `push()`, `pop()`, `shift()`, `unshift()`, `splice()`, `sort()`, `reverse()`</li> + <li><strong>Access/Copying:</strong> `slice()`, `concat()`, `includes()`, `indexOf()`, `join()`</li> + </ul> + <h6>Spread Syntax (`...`)</h6> + <p>Expands array elements where multiple elements/arguments are expected.</p> + <pre><code class="language-javascript">const arr1 = [1, 2]; +const arr2 = [3, 4]; +const combined = [...arr1, ...arr2]; // [1, 2, 3, 4] +const copy = [...arr1]; // Creates a shallow copy + +function sumNumbers(a, b, c) { return a + b + c; } +const nums = [10, 20, 30]; +console.log(sumNumbers(...nums)); // 60 +</code></pre> + </div> + </div> + </div> + <div class="col-lg-4 col-md-6"> + <div class="info-card card-core" id="card-js-objects"> + <div class="card-body"> + <h5><i class="bi bi-diagram-3" aria-hidden="true"></i> Objects & Prototypes</h5> + <div class="card-content-wrapper"> + <p class="summary">Collections of key-value pairs (properties). JS uses <span class="term" data-bs-toggle="tooltip" title="Objects inherit properties/methods from other objects.">prototypal inheritance</span>. Access properties via dot or bracket notation. <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects" target="_blank">MDN Objects</a></p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseJsObjects" aria-expanded="false" aria-controls="collapseJsObjects"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseJsObjects"> + <h6>Key Concepts</h6> + <ul> + <li><strong>Literals:</strong> `const obj = { key: 'value', method() { return this.key; } };`</li> + <li><strong>Property Access:</strong> `obj.key` or `obj['key']`. Bracket notation for dynamic keys.</li> + <li><strong>`Object` Methods:</strong> `Object.keys()`, `Object.values()`, `Object.entries()`, `Object.assign()`, `Object.create()`.</li> + <li><strong>Prototypal Inheritance:</strong> Each object has a prototype object from which it inherits properties. The chain ends with `null`. `Object.getPrototypeOf()` and `__proto__` (legacy). <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain" target="_blank">Prototype Chain</a></li> + </ul> + <p><em>ES6 Classes provide syntactic sugar over this.</em></p> + </div> + </div> + </div> + </div> <!-- /.row --> + </div> <!-- /.schema-container --> + + <!-- II. Modern JavaScript Features (ES6+) --> + <div class="schema-container section-modern" data-section-id="section-modern" data-section-name="Modern JS (ES6+)"> + <h2 class="section-title" id="section-modern-title">Modern JavaScript Features (ES6+)</h2> + <div class="row"> + <div class="col-lg-4 col-md-6"> + <div class="info-card card-modern" id="card-js-arrow-func"> + <div class="card-body"> + <h5><i class="bi bi-arrow-right-short" aria-hidden="true" data-bs-toggle="tooltip" title="Arrow Function Icon"></i> Arrow Functions <span class="version-tag">ES6+</span></h5> + <div class="card-content-wrapper"> + <p class="summary">Concise syntax for writing functions. Importantly, they do not have their own <span class="term" data-bs-toggle="tooltip" title="Arrow functions inherit 'this' from the surrounding (lexical) scope.">`this`</span> context; they inherit it. <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions" target="_blank" rel="noopener noreferrer">MDN Arrow Functions</a></p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseJsArrowFunc" aria-expanded="false" aria-controls="collapseJsArrowFunc"> + Details <i class="bi bi-chevron-down" aria-hidden="true"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseJsArrowFunc"> + <h6>Syntax</h6> + <ul> + <li><strong>Single parameter:</strong> `param => expression` (implicit return)</li> + <li><strong>Multiple parameters:</strong> `(param1, param2) => expression`</li> + <li><strong>No parameters:</strong> `() => expression`</li> + <li><strong>Block body:</strong> `(param1, param2) => { /* statements */ return value; }` (explicit `return` needed)</li> + <li><strong>Object literal return:</strong> `() => ({ key: 'value' })` (wrap in parentheses)</li> + </ul> + <h6>Lexical `this`</h6> + <p>Arrow functions capture the `this` value of the enclosing execution context. They are often useful in callbacks (like `setTimeout` or event listeners) where traditional functions might lose the intended `this`.</p> + <pre><code class="language-javascript">// Traditional function losing 'this' +function Counter() { + this.count = 0; + // Using .bind(this) or assigning this to a variable (self = this) was common + setInterval(function() { + // 'this' here is likely the window or undefined (strict mode) + // this.count++; // Fails or modifies global count + }.bind(this), 1000); // Or use .bind(this) +} + +// Arrow function preserving 'this' +function CounterFixed() { + this.count = 0; + setInterval(() => { + // 'this' here is the CounterFixed instance + this.count++; + console.log(this.count); + }, 1000); +} +// const c = new CounterFixed();</code></pre> + <h6>Limitations</h6> + <p>Cannot be used as constructors (`new`). Do not have their own `arguments` object (use rest parameters `...args` instead). Not suitable for object methods that need their own `this` context pointing to the object itself.</p> + </div> + </div> + </div> + <div class="col-lg-4 col-md-6"> + <div class="info-card card-modern" id="card-js-promises"> + <div class="card-body"> + <h5><i class="bi bi-hourglass-split" aria-hidden="true"></i> Promises <span class="version-tag">ES6+</span></h5> + <div class="card-content-wrapper"> + <p class="summary">Object representing the eventual completion (or failure) of an asynchronous operation. Enables chaining (`.then()`, `.catch()`). <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise" target="_blank">MDN Promise</a></p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseJsPromise" aria-expanded="false" aria-controls="collapseJsPromise"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseJsPromise"> + <h6>States</h6> + <ul> + <li><strong>Pending:</strong> Initial state, neither fulfilled nor rejected.</li> + <li><strong>Fulfilled:</strong> Operation completed successfully.</li> + <li><strong>Rejected:</strong> Operation failed.</li> + </ul> + <h6>Chaining</h6> + <pre><code class="language-javascript">fetch('/api/data') // fetch returns a Promise + .then(response => { + if (!response.ok) { + throw new Error(`HTTP error! Status: ${response.status}`); + } + return response.json(); // .json() also returns a Promise + }) + .then(data => { + console.log('Data received:', data); + }) + .catch(error => { + console.error('Fetch failed:', error); + }) + .finally(() => { + console.log('Fetch attempt finished.'); + }); +</code></pre> + <h6>Static Methods</h6> + <ul> + <li><strong>`Promise.all(iterable)`:</strong> Fulfilled when all promises in iterable fulfill. Rejects if any reject.</li> + <li><strong>`Promise.race(iterable)`:</strong> Settled (fulfilled or rejected) as soon as one promise in iterable settles.</li> + <li><strong>`Promise.allSettled(iterable)`:</strong> Fulfilled when all promises settle (regardless of outcome). Result is an array of status objects.</li> + <li><strong>`Promise.resolve(value)`:</strong> Returns a Promise resolved with the given value.</li> + <li><strong>`Promise.reject(reason)`:</strong> Returns a Promise rejected with the given reason.</li> + </ul> + </div> + </div> + </div> + <div class="col-lg-4 col-md-6"> + <div class="info-card card-modern" id="card-js-async-await"> + <div class="card-body"> + <h5><i class="bi bi-lightning" aria-hidden="true"></i> Async/Await <span class="version-tag">ES2017+</span></h5> + <div class="card-content-wrapper"> + <p class="summary">Syntactic sugar built on Promises, allowing asynchronous code to be written more like synchronous code. Use <span class="term">`async`</span> for functions and <span class="term">`await`</span> to pause for Promises. <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function" target="_blank">MDN Async Function</a></p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseJsAsync" aria-expanded="false" aria-controls="collapseJsAsync"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseJsAsync"> + <h6>Usage</h6> + <ul> + <li><strong>`async` Keyword:</strong> Placed before a function declaration makes it automatically return a Promise.</li> + <li><strong>`await` Keyword:</strong> Can only be used inside an `async` function. Pauses execution until the awaited Promise settles. If fulfilled, returns the resolved value. If rejected, throws the rejection reason.</li> + </ul> + <h6>Example</h6> + <pre><code class="language-javascript">async function fetchData() { + console.log('Fetching data...'); + try { + const response = await fetch('/api/data'); // Pauses here + if (!response.ok) { + throw new Error(`HTTP error! Status: ${response.status}`); + } + const data = await response.json(); // Pauses here + console.log('Data received:', data); + return data; + } catch (error) { + console.error('Fetch failed:', error); + // Handle error or re-throw + throw error; + } finally { + console.log('Fetch attempt finished.'); + } +} + +// Call the async function +fetchData() + .then(result => console.log('Async function finished with:', result)) + .catch(err => console.log('Async function caught error:', err)); +</code></pre> + <h6>Parallel Operations</h6> + <p>Use `Promise.all()` with `await` to run multiple async operations concurrently.</p> + <pre><code class="language-javascript">async function fetchMultiple() { + try { + const [userData, postsData] = await Promise.all([ + fetch('/api/user').then(res => res.json()), + fetch('/api/posts').then(res => res.json()) + ]); + console.log('User:', userData); + console.log('Posts:', postsData); + } catch (error) { + console.error('Failed fetching multiple:', error); + } +} +</code></pre> + </div> + </div> + </div> + <div class="col-lg-4 col-md-6"> + <div class="info-card card-modern" id="card-js-modules"> + <div class="card-body"> + <h5><i class="bi bi-box-arrow-in-down" aria-hidden="true"></i> Modules (ESM) <span class="version-tag">ES6+</span></h5> + <div class="card-content-wrapper"> + <p class="summary">Standard module system for JS. Use <span class="term">`import`</span> to bring in functionality and <span class="term">`export`</span> to make it available. Enables code organization and reusability. <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules" target="_blank">MDN Modules</a></p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseJsModules" aria-expanded="false" aria-controls="collapseJsModules"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseJsModules"> + <h6>Exporting</h6> + <pre><code class="language-javascript">// utils.js +export const PI = 3.14159; + +export function double(n) { + return n * 2; +} + +export default function greet(name) { // Only one default export per module + console.log(`Hello, ${name}!`); +} +</code></pre> + <h6>Importing</h6> + <pre><code class="language-javascript">// main.js +import { PI, double } from './utils.js'; // Named imports +import sayHello from './utils.js'; // Default import (can rename) +// OR import * as Utils from './utils.js'; // Namespace import + +console.log(PI); // 3.14159 +console.log(double(5)); // 10 +sayHello('World'); // Logs: Hello, World! +// Utils.greet('Again'); // Using namespace import +</code></pre> + <h6>Usage Context</h6> + <ul> + <li><strong>Browsers:</strong> Use `<script type="module" src="main.js"></script>`. Handles dependencies automatically.</li> + <li><strong>Node.js:</strong> Use `.mjs` extension or set `"type": "module"` in `package.json`. CommonJS (`require`) still prevalent but ESM is the standard.</li> + </ul> + </div> + </div> + </div> + <div class="col-lg-4 col-md-6"> + <div class="info-card card-modern" id="card-js-classes"> + <div class="card-body"> + <h5><i class="bi bi-building" aria-hidden="true"></i> Classes <span class="version-tag">ES6+</span></h5> + <div class="card-content-wrapper"> + <p class="summary">Syntactic sugar over JavaScript's prototypal inheritance. Provides a cleaner syntax for creating objects and managing inheritance. <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes" target="_blank">MDN Classes</a></p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseJsClasses" aria-expanded="false" aria-controls="collapseJsClasses"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseJsClasses"> + <h6>Defining Classes</h6> + <pre><code class="language-javascript">class Animal { + constructor(name) { + this.name = name; + } + + speak() { + console.log(`${this.name} makes a noise.`); + } +} + +class Dog extends Animal { + constructor(name, breed) { + super(name); // Call parent constructor + this.breed = breed; + } + + speak() { // Override parent method + console.log(`${this.name} barks.`); + } + + fetch() { + console.log(`${this.name} fetches the ball.`); + } +} + +const myDog = new Dog('Rex', 'German Shepherd'); +myDog.speak(); // Rex barks. +myDog.fetch(); // Rex fetches the ball. +console.log(myDog.breed); // German Shepherd +</code></pre> + <h6>Key Features</h6> + <ul> + <li><strong>`constructor` method:</strong> Special method for creating and initializing an object created with a class.</li> + <li><strong>`extends` keyword:</strong> Used for inheritance from a parent class.</li> + <li><strong>`super` keyword:</strong> Used to call corresponding methods of a super class (e.g., `super()` in constructor, `super.methodName()`).</li> + <li><strong>Static methods:</strong> Defined with `static` keyword, called on the class itself, not instances.</li> + <li><strong>Getters & Setters:</strong> Define computed properties.</li> + </ul> + <p><em>Classes are primarily syntactic sugar and do not introduce a new object-oriented inheritance model to JavaScript.</em></p> + </div> + </div> + </div> + <div class="col-lg-4 col-md-6"> + <div class="info-card card-modern" id="card-js-destructuring"> + <div class="card-body"> + <h5><i class="bi bi-arrows-angle-contract" aria-hidden="true"></i> Destructuring <span class="version-tag">ES6+</span></h5> + <div class="card-content-wrapper"> + <p class="summary">Syntax for unpacking values from arrays or properties from objects into distinct variables. Makes code cleaner and more readable. <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment" target="_blank">MDN Destructuring</a></p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseJsDestructuring" aria-expanded="false" aria-controls="collapseJsDestructuring"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseJsDestructuring"> + <h6>Array Destructuring</h6> + <pre><code class="language-javascript">const fruits = ['apple', 'banana', 'cherry']; +const [first, second, third] = fruits; +console.log(first); // apple + +const [a, , c] = fruits; // Skip elements +console.log(c); // cherry + +const [x, ...rest] = fruits; // Rest syntax +console.log(rest); // ['banana', 'cherry'] +</code></pre> + <h6>Object Destructuring</h6> + <pre><code class="language-javascript">const person = { name: 'Alice', age: 30, city: 'New York' }; +const { name, age } = person; +console.log(name); // Alice + +const { name: personName, city } = person; // Rename variables +console.log(personName); // Alice + +const { country = 'USA' } = person; // Default values +console.log(country); // USA + +function greet({ name, age }) { // Destructuring in function parameters + console.log(`Hello ${name}, you are ${age}.`); +} +greet(person); +</code></pre> + <p>Useful for extracting values, assigning to variables, and in function parameters.</p> + </div> + </div> + </div> + </div> <!-- /.row --> + </div> <!-- /.schema-container --> + + <!-- III. Browser Environment & Web APIs --> + <div class="schema-container section-browser" data-section-id="section-browser" data-section-name="Browser APIs"> + <h2 class="section-title" id="section-browser-title">Browser Environment & Web APIs</h2> + <div class="row"> + <div class="col-lg-4 col-md-6"> + <div class="info-card card-browser" id="card-browser-dom"> + <div class="card-body"> + <h5><i class="bi bi-diagram-2" aria-hidden="true"></i> The DOM</h5> + <div class="card-content-wrapper"> + <p class="summary"><span class="term">Document Object Model</span>: A tree-like representation of the HTML document. Allows JS to interact with and manipulate page content, structure, and style. <a href="https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Introduction" target="_blank">MDN DOM Intro</a></p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseBrowserDom" aria-expanded="false" aria-controls="collapseBrowserDom"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseBrowserDom"> + <h6>Key Concepts</h6> + <ul> + <li><strong>Tree Structure:</strong> Represents HTML elements as nested nodes. The `document` object is the root.</li> + <li><strong>`document` Object:</strong> Entry point to the DOM for a page (e.g., `document.body`, `document.head`).</li> + <li><strong>Nodes:</strong> Different types represent elements (Element Node), text content (Text Node), attributes (Attribute Node), comments, etc.</li> + <li><strong>Live vs. Static Collections:</strong> Some DOM methods return live collections (update automatically when DOM changes, e.g., `getElementsByTagName`), others static (snapshot, e.g., `querySelectorAll`).</li> + </ul> + </div> + </div> + </div> + <div class="col-lg-4 col-md-6"> + <div class="info-card card-browser" id="card-browser-dom-manip"> + <div class="card-body"> + <h5><i class="bi bi-pencil-square" aria-hidden="true"></i> DOM Manipulation</h5> + <div class="card-content-wrapper"> + <p class="summary">Selecting elements (e.g., `querySelector`, `getElementById`), modifying content (`textContent`, `innerHTML`), attributes (`setAttribute`), styles (`element.style`), and structure (`createElement`, `appendChild`). <a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Manipulating_documents" target="_blank">MDN Manipulating Docs</a></p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseBrowserDomManip" aria-expanded="false" aria-controls="collapseBrowserDomManip"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseBrowserDomManip"> + <h6>Common Tasks</h6> + <ul> + <li><strong>Selecting:</strong> + <ul> + <li>`document.getElementById('id')`</li> + <li>`document.querySelector('.class')` (first match)</li> + <li>`document.querySelectorAll('tag, .class')` (NodeList)</li> + <li>`document.getElementsByClassName('class')` (HTMLCollection - live)</li> + <li>`document.getElementsByTagName('tag')` (HTMLCollection - live)</li> + </ul> + </li> + <li><strong>Modifying Text:</strong> `element.textContent = 'New text';` (safer, ignores HTML)</li> + <li><strong>Modifying HTML:</strong> `element.innerHTML = '<span>New HTML</span>';` (Use with caution due to XSS risks if content is user-supplied)</li> + <li><strong>Attributes:</strong> `element.setAttribute('href', '#')`, `element.getAttribute('src')`, `element.removeAttribute('disabled')`, `element.hasAttribute('data-custom')`</li> + <li><strong>Classes:</strong> `element.classList.add('active')`, `element.classList.remove('disabled')`, `element.classList.toggle('highlight')`, `element.classList.contains('item')`</li> + <li><strong>Styles:</strong> `element.style.color = 'blue';`, `element.style.display = 'none';` (sets inline styles)</li> + <li><strong>Creating:</strong> `const newDiv = document.createElement('div');`</li> + <li><strong>Appending/Inserting:</strong> `parentElement.appendChild(newChild);`, `parentElement.insertBefore(newChild, referenceChild);`, `element.append(...nodesOrStrings);`, `element.prepend(...nodesOrStrings);`</li> + <li><strong>Removing:</strong> `element.remove();` or `parentElement.removeChild(element);`</li> + </ul> + </div> + </div> + </div> + <div class="col-lg-4 col-md-6"> + <div class="info-card card-browser" id="card-browser-fetch"> + <div class="card-body"> + <h5><i class="bi bi-cloud-download" aria-hidden="true"></i> Fetch API</h5> + <div class="card-content-wrapper"> + <p class="summary">Modern interface for making network requests (HTTP). Promise-based. Used to retrieve data from APIs or send data to servers. <a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch" target="_blank">MDN Using Fetch</a></p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseBrowserFetch" aria-expanded="false" aria-controls="collapseBrowserFetch"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseBrowserFetch"> + <h6>Basic GET Request</h6> + <pre><code class="language-javascript">fetch('https://api.example.com/users') + .then(response => { + if (!response.ok) { // Check for HTTP errors (4xx, 5xx) + throw new Error(`Network response was not ok: ${response.statusText} (${response.status})`); + } + return response.json(); // Parse JSON body + }) + .then(users => { + console.log('Users:', users); + }) + .catch(error => { + console.error('Fetch error:', error); // Handles network errors and thrown errors + }); +</code></pre> + <h6>POST Request with JSON</h6> + <pre><code class="language-javascript">async function postData(url = '', data = {}) { + try { + const response = await fetch(url, { + method: 'POST', // *GET, POST, PUT, DELETE, etc. + headers: { + 'Content-Type': 'application/json' + // 'Authorization': 'Bearer YOUR_TOKEN_HERE' // Example header + }, + body: JSON.stringify(data) // Body data type must match "Content-Type" header + }); + if (!response.ok) { + throw new Error(`HTTP error! Status: ${response.status}`); + } + return await response.json(); // Parses JSON response body + } catch (error) { + console.error('Error posting data:', error); + throw error; + } +} + +postData('https://api.example.com/users', { name: 'John Doe', job: 'Developer' }) + .then(data => console.log('Success:', data)); +</code></pre> + <h6>Response Object</h6> + <p>The `Response` object contains status (`.status`, `.statusText`), headers (`.headers`), and methods to read the body (`.json()`, `.text()`, `.blob()`, `.formData()`), which themselves return Promises.</p> + <h6>Request Options</h6> + <p>The second argument to `fetch` is an options object that can include `method`, `headers`, `body`, `mode` (cors, no-cors), `credentials`, `cache`, `signal` (for AbortController), etc.</p> + </div> + </div> + </div> + <div class="col-lg-4 col-md-6"> + <div class="info-card card-browser" id="card-browser-events"> + <div class="card-body"> + <h5><i class="bi bi-mouse" aria-hidden="true"></i> Event Handling</h5> + <div class="card-content-wrapper"> + <p class="summary">Respond to user interactions (clicks, key presses, mouse moves) or browser events (load, resize). Use <span class="term">`addEventListener`</span>. Understand event object, bubbling/capturing. <a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events" target="_blank">MDN Events</a></p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseBrowserEvents" aria-expanded="false" aria-controls="collapseBrowserEvents"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseBrowserEvents"> + <h6>Attaching Listeners</h6> + <pre><code class="language-javascript">const button = document.getElementById('myButton'); + +function handleClick(event) { + console.log('Button clicked!', event.target); + // event.preventDefault(); // Stop default action (e.g., form submission) + // event.stopPropagation(); // Stop event from bubbling up +} + +button.addEventListener('click', handleClick); +// To remove: button.removeEventListener('click', handleClick); +</code></pre> + <h6>Event Object</h6> + <p>The callback function receives an `Event` object with details about the event (e.g., `event.target`, `event.type`, `event.clientX`, `event.key`).</p> + <h6>Event Phases</h6> + <ul> + <li><strong>Capturing Phase:</strong> Event travels down from window to target.</li> + <li><strong>Target Phase:</strong> Event reaches the target element.</li> + <li><strong>Bubbling Phase:</strong> Event travels up from target to window (default for most events).</li> + </ul> + <h6>Event Delegation</h6> + <p>Attach a single event listener to a parent element to manage events for multiple child elements, especially dynamically added ones. Check `event.target` within the handler.</p> + <!-- Detailed content needed: Event object, common events (click, mouseover, keydown, submit, load), bubbling/capturing, preventDefault, stopPropagation, event delegation --> + </div> + </div> + </div> + </div> <!-- /.row --> + </div> <!-- /.schema-container --> + + <!-- IV. Frontend Frameworks & Libraries --> + <div class="schema-container section-frameworks" data-section-id="section-frameworks" data-section-name="Frameworks"> + <h2 class="section-title" id="section-frameworks-title">Frontend Frameworks & Libraries</h2> + <div class="row"> + <!-- React Cards --> + <div class="col-lg-4 col-md-6"> + <div class="info-card card-react" id="card-react-overview"> + <div class="card-body"> + <h5><i class="bi bi-gem" aria-hidden="true"></i> React Overview</h5> + <div class="card-content-wrapper"> + <p class="summary">Popular library for building user interfaces using a <span class="term" data-bs-toggle="tooltip" title="JS objects representing the desired UI state. React updates the actual DOM efficiently.">Virtual DOM</span> and a <span class="term" data-bs-toggle="tooltip" title="Building UIs from reusable pieces (components).">component-based</span> architecture. Focuses on declarative UI. <a href="https://react.dev/" target="_blank">React Docs</a></p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseReactOverview" aria-expanded="false" aria-controls="collapseReactOverview"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseReactOverview"> + <h6>Key Concepts</h6> + <ul> + <li><strong>Components:</strong> Reusable UI pieces (typically functions returning JSX).</li> + <li><strong>JSX:</strong> Syntax extension allowing HTML-like code in JS.</li> + <li><strong>Props:</strong> Data passed down from parent to child components (read-only).</li> + <li><strong>State:</strong> Data managed *within* a component that can change over time.</li> + <li><strong>Hooks:</strong> Functions (like `useState`, `useEffect`) letting you "hook into" React state and lifecycle features from function components.</li> + <li><strong>Virtual DOM:</strong> In-memory representation used to optimize DOM updates ("diffing").</li> + <li><strong>Unidirectional Data Flow:</strong> Data flows down from parent to child components via props. State changes trigger re-renders.</li> + </ul> + </div> + </div> + </div> + <div class="col-lg-4 col-md-6"> + <div class="info-card card-react" id="card-react-hooks"> + <div class="card-body"> + <h5><i class="bi bi-life-preserver" aria-hidden="true"></i> State & Lifecycle (Hooks) <span class="version-tag">React 16.8+</span></h5> + <div class="card-content-wrapper"> + <p class="summary">Manage component state (`useState`) and side effects (`useEffect`) in functional components. Share state with `useContext`. <a href="https://react.dev/reference/react/hooks" target="_blank">React Hooks Reference</a></p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseReactHooks" aria-expanded="false" aria-controls="collapseReactHooks"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseReactHooks"> + <h6>Core Hooks</h6> + <ul> + <li><strong>`useState(initialState)`:</strong> Returns a stateful value and a function to update it. Re-renders component on update. + <pre><code class="language-javascript">const [count, setCount] = useState(0); +// ... +setCount(prevCount => prevCount + 1); // Functional update +// setCount(count + 1); // Direct update</code></pre> + </li> + <li><strong>`useEffect(setup, dependencies?)`:</strong> Performs side effects (data fetching, subscriptions, manual DOM changes). Runs after render. `dependencies` array controls re-run behavior. Empty array `[]` runs once on mount/unmount. No array runs after every render. + <pre><code class="language-javascript">// Fetch data on mount +useEffect(() => { + let isMounted = true; // Prevent state update on unmounted component + fetchData().then(data => { + if (isMounted) setData(data); + }); + return () => { isMounted = false; }; // Cleanup +}, []); // Runs only once after initial render + +// Run when 'userId' prop changes +useEffect(() => { + console.log('User ID changed:', userId); + // Cleanup function (optional) + return () => { + console.log('Cleaning up effect for old userId'); + }; +}, [userId]);</code></pre> + </li> + <li><strong>`useContext(Context)`:</strong> Subscribes to React context to read its value. Avoids prop drilling. + <pre><code class="language-javascript">// ThemeContext.js +// export const ThemeContext = React.createContext('light'); +const theme = useContext(ThemeContext); +// ... use theme value (e.g., <div className={`App ${theme}`}>)</code></pre> + </li> + </ul> + <h6>Other Common Hooks</h6> + <p>`useReducer` (complex state logic), `useCallback` (memoize callbacks), `useMemo` (memoize computed values), `useRef` (access DOM/persist mutable values), `useLayoutEffect` (synchronous DOM mutations).</p> + </div> + </div> + </div> + <div class="col-lg-4 col-md-6"> + <div class="info-card card-react" id="card-react-jsx"> + <div class="card-body"> + <h5><i class="bi bi-filetype-jsx" aria-hidden="true"></i> JSX</h5> + <div class="card-content-wrapper"> + <p class="summary"><span class="term">JavaScript XML</span>: Syntax extension allowing HTML-like syntax within JavaScript. Transpiled to `React.createElement()` calls. <a href="https://react.dev/learn/writing-markup-with-jsx" target="_blank">React JSX Intro</a></p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseReactJsx" aria-expanded="false" aria-controls="collapseReactJsx"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseReactJsx"> + <h6>Key Features</h6> + <ul> + <li><strong>Expressions:</strong> Embed JS expressions using curly braces `{}`. E.g., `<h1>Hello, {user.name}</h1>`.</li> + <li><strong>Attributes:</strong> Use camelCase for HTML attributes (e.g., `className` for `class`, `htmlFor` for `for`). Boolean attributes can be written shorthand (e.g., `disabled` is same as `disabled={true}`).</li> + <li><strong>Styling:</strong> Pass a style object to the `style` attribute: `style={{ color: 'blue', fontSize: '16px' }}`.</li> + <li><strong>Fragments:</strong> Use `<>` or `<React.Fragment>` to return multiple elements without a wrapper div.</li> + <li><strong>Comments:</strong> Use JS comments within braces: `{/* This is a comment */}`.</li> + <li><strong>Self-closing tags:</strong> Required for elements without children, e.g. `<img src="..." />`.</li> + </ul> + <pre><code class="language-jsx">function Greeting({ name, items }) { + const isLoggedIn = true; + const listItems = items.map(item => <li key={item.id}>{item.text}</li>); + + return ( + <> {/* React Fragment */} + <h1 className="title" style={{ color: 'purple', fontWeight: 'bold' }}> + Hello, {name}! + </h1> + {isLoggedIn && <p>Welcome back!</p>} {/* Conditional rendering */} + {items.length > 0 ? ( + <ul>{listItems}</ul> + ) : ( + <p>No items to display.</p> + )} + <input type="text" placeholder="Enter something" disabled /> + </> + ); +} +</code></pre> + </div> + </div> + </div> + <div class="col-lg-4 col-md-6"> + <div class="info-card card-vue" id="card-vue-overview"> + <div class="card-body"> + <h5><i class="bi bi-triangle" aria-hidden="true"></i> Vue.js Overview</h5> + <div class="card-content-wrapper"> + <p class="summary">Progressive framework for building UIs. Known for its approachability, template syntax, and reactivity system. Offers Options API and Composition API. <a href="https://vuejs.org/" target="_blank">Vue Docs</a></p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseVueOverview" aria-expanded="false" aria-controls="collapseVueOverview"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseVueOverview"> + <h6>Key Concepts</h6> + <ul> + <li><strong>Declarative Rendering:</strong> HTML-based template syntax.</li> + <li><strong>Reactivity:</strong> Data changes automatically update the DOM.</li> + <li><strong>Components:</strong> Single File Components (`.vue` files) with template, script, and style sections.</li> + <li><strong>Options API:</strong> Organizes component logic using options like `data`, `methods`, `computed`, `watch`, lifecycle hooks.</li> + <li><strong>Composition API (Vue 3+):</strong> More flexible way to organize logic using functions like `ref`, `reactive`, `computed`, `watch`, `onMounted`.</li> + <li><strong>Directives:</strong> Special attributes with `v-` prefix (e.g., `v-if`, `v-for`, `v-bind`, `v-on`).</li> + </ul> + <p><em>More detail on template syntax, Options vs Composition API needed.</em></p> + </div> + </div> + </div> + <div class="col-lg-4 col-md-6"> + <div class="info-card card-angular" id="card-angular-overview"> + <div class="card-body"> + <h5><i class="bi bi-shield-shaded" aria-hidden="true"></i> Angular Overview</h5> + <div class="card-content-wrapper"> + <p class="summary">A comprehensive platform and framework for building complex client applications in HTML and TypeScript. Opinionated structure with powerful features. <a href="https://angular.io/" target="_blank">Angular Docs</a></p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseAngularOverview" aria-expanded="false" aria-controls="collapseAngularOverview"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseAngularOverview"> + <h6>Key Concepts</h6> + <ul> + <li><strong>TypeScript-based:</strong> Strong typing is a core feature.</li> + <li><strong>Components & Templates:</strong> Building blocks of UI, with HTML templates and component logic.</li> + <li><strong>Modules (NgModules):</strong> Organize components, directives, pipes, and services.</li> + <li><strong>Dependency Injection (DI):</strong> Built-in system for managing dependencies.</li> + <li><strong>Services:</strong> Reusable logic, often for data fetching or business rules.</li> + <li><strong>Routing:</strong> Powerful client-side navigation.</li> + <li><strong>RxJS:</strong> Heavily used for asynchronous operations and event handling (Observables).</li> + <li><strong>Angular CLI:</strong> Essential for project creation, generation, building, and testing.</li> + </ul> + <p><em>More detail on data binding, directives, pipes, and forms needed.</em></p> + </div> + </div> + </div> + <div class="col-lg-4 col-md-6"> + <div class="info-card card-svelte" id="card-svelte-overview"> + <div class="card-body"> + <h5><i class="bi bi-fire" aria-hidden="true"></i> Svelte Overview</h5> + <div class="card-content-wrapper"> + <p class="summary">A radical new approach to building UIs. Svelte compiles your components into highly efficient imperative code that surgically updates the DOM. <a href="https://svelte.dev/" target="_blank">Svelte Docs</a></p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseSvelteOverview" aria-expanded="false" aria-controls="collapseSvelteOverview"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseSvelteOverview"> + <h6>Key Concepts</h6> + <ul> + <li><strong>Compiler, not a Runtime Library:</strong> Shifts work from the browser to the build step.</li> + <li><strong>No Virtual DOM:</strong> Generates code that updates the DOM directly.</li> + <li><strong>Reactive by Default:</strong> Assignments to variables trigger updates (`let count = 0; count++;`).</li> + <li><strong>Single File Components (`.svelte`):</strong> Combine script, template, and style in one file.</li> + <li><strong>Stores:</strong> Built-in mechanism for managing state outside components (readable, writable, derived).</li> + <li><strong>Transitions & Animations:</strong> First-class support for UI animations.</li> + </ul> + <p><em>More detail on template syntax, reactive declarations (`$: `), stores, and event handling needed.</em></p> + </div> + </div> + </div> + </div> <!-- /.row --> + </div> <!-- /.schema-container --> + + <!-- V. State Management Patterns & Libraries --> + <div class="schema-container section-state" data-section-id="section-state" data-section-name="State Mgt"> + <h2 class="section-title" id="section-state-title">State Management Patterns & Libraries</h2> + <div class="row"> + <div class="col-lg-4 col-md-6"> + <div class="info-card card-state" id="card-state-concepts"> + <div class="card-body"> + <h5><i class="bi bi-diagram-3-fill" aria-hidden="true"></i> State Management Concepts</h5> + <div class="card-content-wrapper"> + <p class="summary">Strategies for handling data that changes over time in applications. Distinguish <span class="term">local state</span> (within a component) from <span class="term">global state</span> (shared across components). Avoid <span class="term" data-bs-toggle="tooltip" title="Passing props through many intermediate components.">prop drilling</span>. <a href="https://react.dev/learn/sharing-state-between-components" target="_blank">React State Sharing</a></p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseStateConcepts" aria-expanded="false" aria-controls="collapseStateConcepts"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseStateConcepts"> + <h6>Types of State</h6> + <ul> + <li><strong>Local State:</strong> Managed within a single component (e.g., form input values, UI toggles). Often handled by component's internal state mechanism (e.g., `useState` in React).</li> + <li><strong>Global State:</strong> Shared across multiple components, often unrelated in the component tree (e.g., user authentication status, theme).</li> + </ul> + <h6>Challenges</h6> + <ul> + <li><strong>Prop Drilling:</strong> Passing data through many layers of intermediate components that don't directly use the data.</li> + <li><strong>Complexity:</strong> Managing how and when state updates occur, especially in larger applications.</li> + <li><strong>Debugging:</strong> Tracing state changes and identifying sources of bugs.</li> + </ul> + <p><em>Choosing the right state management approach depends on application size and complexity.</em></p> + </div> + </div> + </div> + <div class="col-lg-4 col-md-6"> + <div class="info-card card-state card-react" id="card-state-context"> <!-- Specific react color --> + <div class="card-body"> + <h5><i class="bi bi-share" aria-hidden="true"></i> React Context API <span class="version-tag">React 16.3+</span></h5> + <div class="card-content-wrapper"> + <p class="summary">Built-in React mechanism to share state down the component tree without prop drilling. Use `createContext`, `Provider`, and `useContext`. <a href="https://react.dev/learn/passing-data-deeply-with-context" target="_blank">React Context Docs</a></p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseStateContext" aria-expanded="false" aria-controls="collapseStateContext"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseStateContext"> + <h6>Usage</h6> + <pre><code class="language-javascript">// 1. Create Context +// MyContext.js +import React from 'react'; +export const MyContext = React.createContext(null); // Default value + +// 2. Provide Context Value +// App.js +import { MyContext } from './MyContext'; +function App() { + const sharedValue = "Hello from Context!"; + return ( + <MyContext.Provider value={sharedValue}> + <MyComponent /> + </MyContext.Provider> + ); +} + +// 3. Consume Context Value +// MyComponent.js +import React, { useContext } from 'react'; +import { MyContext } from './MyContext'; +function MyComponent() { + const value = useContext(MyContext); + return <div>Shared Value: {value}</div>; +} +</code></pre> + <h6>Considerations</h6> + <ul> + <li>Good for low-frequency updates or relatively static data (e.g., theme, user info).</li> + <li>Can cause performance issues if the context value updates frequently and many components consume it, as all consumers re-render.</li> + <li>Often combined with `useReducer` for more complex state management within a context.</li> + </ul> + </div> + </div> + </div> + <div class="col-lg-4 col-md-6"> + <div class="info-card card-state" id="card-state-redux"> + <div class="card-body"> + <h5><i class="bi bi-arrow-repeat" aria-hidden="true"></i> Redux / RTK</h5> + <div class="card-content-wrapper"> + <p class="summary">Predictable state container for JS apps. Centralized store, immutable updates via <span class="term">reducers</span> triggered by <span class="term">actions</span>. <span class="term">Redux Toolkit (RTK)</span> is the modern standard. <a href="https://redux-toolkit.js.org/" target="_blank">Redux Toolkit Docs</a></p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseStateRedux" aria-expanded="false" aria-controls="collapseStateRedux"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseStateRedux"> + <h6>Core Principles (Classic Redux)</h6> + <ul> + <li><strong>Single Source of Truth:</strong> State of the whole application is stored in one object tree (the store).</li> + <li><strong>State is Read-Only:</strong> The only way to change state is by emitting an action (an object describing what happened).</li> + <li><strong>Changes are made with Pure Functions:</strong> Reducers (pure functions) specify how state changes in response to actions.</li> + </ul> + <h6>Redux Toolkit (RTK)</h6> + <p>Simplifies Redux development by providing:</p> + <ul> + <li><strong>`configureStore()`:</strong> Sets up a well-configured store with good defaults (e.g., Redux DevTools).</li> + <li><strong>`createSlice()`:</strong> Generates action creators and action types automatically, and allows writing "mutating" reducer logic with Immer.</li> + <li><strong>`createAsyncThunk()`:</strong> For handling asynchronous actions (e.g., API calls).</li> + </ul> + <p><em>Example of `createSlice` needed.</em></p> + </div> + </div> + </div> + <div class="col-lg-4 col-md-6"> + <div class="info-card card-state card-react" id="card-state-zustand"> + <div class="card-body"> + <h5><i class="bi bi-lightbulb" aria-hidden="true"></i> Zustand</h5> + <div class="card-content-wrapper"> + <p class="summary">A small, fast, and scalable bearbones state-management solution for React using simplified flux principles. Hook-based API. <a href="https://github.com/pmndrs/zustand" target="_blank">Zustand GitHub</a></p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseStateZustand" aria-expanded="false" aria-controls="collapseStateZustand"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseStateZustand"> + <h6>Key Features</h6> + <ul> + <li><strong>Minimalistic:</strong> Very little boilerplate.</li> + <li><strong>Hook-based:</strong> Create a store, bind it to components using a custom hook.</li> + <li><strong>Unopinionated:</strong> Flexible, can be used for simple or complex state.</li> + <li><strong>Middleware Support:</strong> For devtools, persistence, etc.</li> + </ul> + <pre><code class="language-javascript">// store.js +import { create } from 'zustand'; + +const useStore = create((set) => ({ + bears: 0, + increasePopulation: () => set((state) => ({ bears: state.bears + 1 })), + removeAllBears: () => set({ bears: 0 }), +})); + +export default useStore; + +// MyComponent.js +import useStore from './store'; + +function BearCounter() { + const bears = useStore((state) => state.bears); + return <h1>{bears} around here ...</h1>; +} + +function Controls() { + const increasePopulation = useStore((state) => state.increasePopulation); + return <button onClick={increasePopulation}>one up</button>; +} +</code></pre> + </div> + </div> + </div> + </div> <!-- /.row --> + </div> <!-- /.schema-container --> + + <!-- VI. Ecosystem & Tooling --> + <div class="schema-container section-tooling" data-section-id="section-tooling" data-section-name="Tooling"> + <h2 class="section-title" id="section-tooling-title">Ecosystem & Tooling</h2> + <div class="row"> + <div class="col-lg-4 col-md-6"> + <div class="info-card card-tooling" id="card-tooling-npm"> + <div class="card-body"> + <h5><i class="bi bi-box" aria-hidden="true"></i> Package Managers</h5> + <div class="card-content-wrapper"> + <p class="summary"><span class="term">npm</span>, <span class="term">yarn</span>, <span class="term">pnpm</span> manage project dependencies listed in `package.json`. Install, update, and remove external libraries (packages). <a href="https://docs.npmjs.com/" target="_blank">npm Docs</a></p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseToolingNpm" aria-expanded="false" aria-controls="collapseToolingNpm"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseToolingNpm"> + <h6>`package.json`</h6> + <ul> + <li><strong>`dependencies`</strong>: Packages required for production.</li> + <li><strong>`devDependencies`</strong>: Packages for development (e.g., linters, testing tools).</li> + <li><strong>`scripts`</strong>: Custom commands (e.g., `npm start`, `npm run build`).</li> + </ul> + <h6>Common Commands</h6> + <ul> + <li>`npm install <package>` or `yarn add <package>`</li> + <li>`npm install` or `yarn install` (or just `yarn`)</li> + <li>`npm uninstall <package>` or `yarn remove <package>`</li> + <li>`npm update <package>` or `yarn upgrade <package>`</li> + <li>`npx <command>` (Execute package binaries)</li> + </ul> + <p><em>Consider `package-lock.json` or `yarn.lock` for deterministic installs.</em></p> + </div> + </div> + </div> + <div class="col-lg-4 col-md-6"> + <div class="info-card card-tooling" id="card-tooling-bundlers"> + <div class="card-body"> + <h5><i class="bi bi-boxes" aria-hidden="true"></i> Module Bundlers</h5> + <div class="card-content-wrapper"> + <p class="summary"><span class="term">Vite</span>, <span class="term">Webpack</span>, <span class="term">Parcel</span> process JS modules, assets (CSS, images) and bundle them for browser use. Handle transformations, optimization, dev server. <a href="https://vitejs.dev/" target="_blank">Vite</a> | <a href="https://webpack.js.org/" target="_blank">Webpack</a></p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseToolingBundlers" aria-expanded="false" aria-controls="collapseToolingBundlers"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseToolingBundlers"> + <h6>Key Functions</h6> + <ul> + <li><strong>Dependency Graph:</strong> Traverses `import` statements to build a graph of all modules.</li> + <li><strong>Transformations:</strong> Via plugins/loaders (e.g., Babel for JS, PostCSS for CSS, TypeScript compilation).</li> + <li><strong>Optimization:</strong> Minification, tree-shaking (removing unused code), code splitting.</li> + <li><strong>Development Server:</strong> Provides local server with Hot Module Replacement (HMR) for faster development.</li> + </ul> + <h6>Vite vs. Webpack</h6> + <ul> + <li><strong>Vite:</strong> Extremely fast dev server (uses native ES modules). Simpler configuration. Good for modern projects.</li> + <li><strong>Webpack:</strong> Highly configurable and mature. Extensive plugin ecosystem. Can be complex to set up.</li> + </ul> + <p><em>Configuration examples for Vite and Webpack would be useful here.</em></p> + </div> + </div> + </div> + <div class="col-lg-4 col-md-6"> + <div class="info-card card-tooling" id="card-tooling-ts"> + <div class="card-body"> + <h5><i class="bi bi-filetype-tsx" aria-hidden="true"></i> TypeScript Integration</h5> + <div class="card-content-wrapper"> + <p class="summary"><span class="term">TypeScript</span> adds static typing to JS. Improves code maintainability and reduces runtime errors. Integrates well with frameworks and build tools. <a href="https://www.typescriptlang.org/docs/" target="_blank">TypeScript Docs</a></p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseToolingTs" aria-expanded="false" aria-controls="collapseToolingTs"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseToolingTs"> + <h6>Benefits</h6> + <ul> + <li><strong>Early Error Detection:</strong> Catch type errors during development, not at runtime.</li> + <li><strong>Improved Readability & Maintainability:</strong> Types make code easier to understand and refactor.</li> + <li><strong>Better Tooling:</strong> Enhanced autocompletion, refactoring, and navigation in IDEs.</li> + </ul> + <h6>Core Concepts</h6> + <ul> + <li><strong>Basic Types:</strong> `string`, `number`, `boolean`, `any`, `unknown`, `void`, `null`, `undefined`.</li> + <li><strong>Interfaces & Types:</strong> Define shapes of objects.</li> + <li><strong>Generics:</strong> Create reusable components that can work over a variety of types.</li> + <li><strong>`tsconfig.json`:</strong> Compiler options for the TypeScript project.</li> + </ul> + <p><em>Setup examples with React/Vue and common patterns needed.</em></p> + </div> + </div> + </div> + <div class="col-lg-4 col-md-6"> + <div class="info-card card-tooling" id="card-tooling-testing"> + <div class="card-body"> + <h5><i class="bi bi-clipboard2-check" aria-hidden="true"></i> Testing Frameworks</h5> + <div class="card-content-wrapper"> + <p class="summary">Verify code correctness. <span class="term">Jest</span> / <span class="term">Vitest</span> for unit/integration. <span class="term">React Testing Library</span> for component tests. <span class="term">Cypress</span> / <span class="term">Playwright</span> for E2E tests. <a href="https://jestjs.io/" target="_blank">Jest</a> | <a href="https://testing-library.com/" target="_blank">Testing Library</a></p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseToolingTesting" aria-expanded="false" aria-controls="collapseToolingTesting"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseToolingTesting"> + <h6>Types of Tests</h6> + <ul> + <li><strong>Unit Tests:</strong> Test individual functions or small pieces of code in isolation. (e.g., Jest, Vitest, Mocha, Jasmine).</li> + <li><strong>Integration Tests:</strong> Test how multiple units work together.</li> + <li><strong>Component Tests:</strong> Test UI components in isolation, focusing on user interaction. (e.g., React Testing Library, Vue Testing Library).</li> + <li><strong>End-to-End (E2E) Tests:</strong> Test the entire application flow from the user's perspective in a real browser. (e.g., Cypress, Playwright, Puppeteer).</li> + </ul> + <h6>Popular Tools</h6> + <ul> + <li><strong>Jest / Vitest:</strong> Popular test runners with built-in assertion libraries and mocking capabilities. Vitest is Vite-native and fast.</li> + <li><strong>Testing Library (RTL, VTL):</strong> Encourages testing components by interacting with them as a user would.</li> + <li><strong>Mocking Libraries:</strong> Jest has built-in mocking. Sinon.JS is another option.</li> + </ul> + <p><em>Basic assertion examples for Jest/Vitest needed.</em></p> + </div> + </div> + </div> + <div class="col-lg-4 col-md-6"> + <div class="info-card card-tooling" id="card-tooling-devtools"> + <div class="card-body"> + <h5><i class="bi bi-tools" aria-hidden="true"></i> Browser DevTools</h5> + <div class="card-content-wrapper"> + <p class="summary">Essential suite of tools built into browsers for debugging, inspecting DOM/CSS, performance profiling, network analysis, and more. <a href="https://developer.chrome.com/docs/devtools/" target="_blank">Chrome DevTools</a></p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseToolingDevtools" aria-expanded="false" aria-controls="collapseToolingDevtools"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseToolingDevtools"> + <h6>Key Panels</h6> + <ul> + <li><strong>Elements:</strong> Inspect and edit the DOM tree and CSS styles.</li> + <li><strong>Console:</strong> View logs, run JavaScript commands, interact with the page.</li> + <li><strong>Sources:</strong> Debug JavaScript code (breakpoints, call stack, watch expressions).</li> + <li><strong>Network:</strong> Inspect network requests and responses.</li> + <li><strong>Performance:</strong> Profile runtime performance, identify bottlenecks.</li> + <li><strong>Application:</strong> Inspect storage (localStorage, sessionStorage, cookies), service workers, manifest.</li> + <li><strong>Lighthouse:</strong> (In Chrome) Audit for performance, accessibility, SEO, PWA.</li> + </ul> + <p><em>Framework-specific DevTools extensions (React DevTools, Vue Devtools) are also invaluable.</em></p> + </div> + </div> + </div> + <div class="col-lg-4 col-md-6"> + <div class="info-card card-tooling" id="card-tooling-linters"> + <div class="card-body"> + <h5><i class="bi bi-check2-square" aria-hidden="true"></i> Linters & Formatters</h5> + <div class="card-content-wrapper"> + <p class="summary"><span class="term">ESLint</span> analyzes code for potential errors and style issues. <span class="term">Prettier</span> automatically formats code for consistent style. Improves code quality and team consistency. <a href="https://eslint.org/" target="_blank">ESLint</a> | <a href="https://prettier.io/" target="_blank">Prettier</a></p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseToolingLinters" aria-expanded="false" aria-controls="collapseToolingLinters"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseToolingLinters"> + <h6>ESLint</h6> + <ul> + <li>Static analysis tool to find problematic patterns or code that doesn't adhere to style guidelines.</li> + <li>Configurable with rules (e.g., `.eslintrc.js`).</li> + <li>Plugins for specific frameworks (e.g., `eslint-plugin-react`) and TypeScript (`@typescript-eslint/parser`).</li> + </ul> + <h6>Prettier</h6> + <ul> + <li>Opinionated code formatter. Parses code and re-prints it with consistent style.</li> + <li>Integrates well with ESLint (e.g., `eslint-config-prettier` to turn off conflicting ESLint style rules).</li> + <li>Often run on save in IDEs or as a pre-commit hook.</li> + </ul> + <p><em>Using both together provides powerful code quality enforcement.</em></p> + </div> + </div> + </div> + </div> <!-- /.row --> + </div> <!-- /.schema-container --> + + <!-- VII. Advanced Concepts & Patterns --> + <div class="schema-container section-advanced" data-section-id="section-advanced" data-section-name="Advanced"> + <h2 class="section-title" id="section-advanced-title">Advanced Concepts & Patterns</h2> + <div class="row"> + <div class="col-lg-4 col-md-6"> + <div class="info-card card-advanced" id="card-advanced-perf"> + <div class="card-body"> + <h5><i class="bi bi-speedometer2" aria-hidden="true"></i> Performance Optimization</h5> + <div class="card-content-wrapper"> + <p class="summary">Techniques to improve load times and runtime speed. Includes <span class="term">code splitting</span>, <span class="term">lazy loading</span> components/routes, <span class="term">memoization</span> (React.memo, useMemo). <a href="https://web.dev/performance/" target="_blank">web.dev Performance</a></p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseAdvancedPerf" aria-expanded="false" aria-controls="collapseAdvancedPerf"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseAdvancedPerf"> + <h6>Key Techniques</h6> + <ul> + <li><strong>Code Splitting:</strong> Breaking down large bundles into smaller chunks that can be loaded on demand. (Webpack, Vite support this).</li> + <li><strong>Lazy Loading:</strong> Deferring the loading of non-critical resources (images, components, routes) until they are needed. (e.g., `React.lazy`, dynamic `import()`).</li> + <li><strong>Memoization:</strong> Caching results of expensive function calls and re-using them if inputs haven't changed. (e.g., `React.memo`, `useMemo`, `useCallback` in React).</li> + <li><strong>Virtualization (Windowing):</strong> Rendering only visible items in long lists or large tables to improve performance. (e.g., `react-window`, `react-virtualized`).</li> + <li><strong>Tree Shaking:</strong> Bundlers remove unused code from the final bundle.</li> + <li><strong>Optimizing Images:</strong> Compression, responsive images (`<picture>`, `srcset`), modern formats (WebP, AVIF).</li> + <li><strong>Caching:</strong> Browser caching, CDN caching.</li> + </ul> + <p><em>Measure performance with Browser DevTools (Performance, Lighthouse tabs) and Core Web Vitals.</em></p> + </div> + </div> + </div> + <div class="col-lg-4 col-md-6"> + <div class="info-card card-advanced" id="card-advanced-a11y"> + <div class="card-body"> + <h5><i class="bi bi-person-check" aria-hidden="true"></i> Accessibility (a11y)</h5> + <div class="card-content-wrapper"> + <p class="summary">Designing web applications usable by everyone, including people with disabilities. Use <span class="term">semantic HTML</span>, <span class="term">ARIA attributes</span>, ensure keyboard navigation, color contrast. <a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility" target="_blank">MDN Accessibility</a></p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseAdvancedA11y" aria-expanded="false" aria-controls="collapseAdvancedA11y"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseAdvancedA11y"> + <h6>Key Principles (WCAG)</h6> + <p>Perceivable, Operable, Understandable, Robust.</p> + <h6>Practical Steps</h6> + <ul> + <li><strong>Semantic HTML:</strong> Use HTML elements for their intended purpose (e.g., `<button>`, `<nav>`, `<main>`).</li> + <li><strong>ARIA (Accessible Rich Internet Applications):</strong> Use `role` and `aria-*` attributes to provide additional semantics for assistive technologies when native HTML is insufficient.</li> + <li><strong>Keyboard Navigation:</strong> Ensure all interactive elements are focusable and operable via keyboard. Manage focus order.</li> + <li><strong>Focus Management:</strong> Visually indicate focused elements. Programmatically manage focus in dynamic UIs.</li> + <li><strong>Alternative Text:</strong> Provide `alt` text for images.</li> + <li><strong>Color Contrast:</strong> Ensure sufficient contrast between text and background.</li> + <li><strong>Forms:</strong> Associate labels with inputs (`<label for="...">`). Provide clear error messages.</li> + <li><strong>Testing:</strong> Use automated tools (e.g., Axe, Lighthouse), manual keyboard testing, screen reader testing.</li> + </ul> + </div> + </div> + </div> + <div class="col-lg-4 col-md-6"> + <div class="info-card card-advanced" id="card-advanced-pwa"> + <div class="card-body"> + <h5><i class="bi bi-phone" aria-hidden="true"></i> Progressive Web Apps (PWAs)</h5> + <div class="card-content-wrapper"> + <p class="summary">Web apps that use modern web capabilities to deliver an app-like experience. Key features: installable, offline support (via <span class="term">Service Workers</span>), push notifications. <a href="https://web.dev/progressive-web-apps/" target="_blank">web.dev PWAs</a></p> + <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseAdvancedPwa" aria-expanded="false" aria-controls="collapseAdvancedPwa"> + Details <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseAdvancedPwa"> + <h6>Core Technologies</h6> + <ul> + <li><strong>Service Workers:</strong> Scripts that run in the background, separate from the web page. Enable caching for offline support, background sync, push notifications.</li> + <li><strong>Web App Manifest:</strong> JSON file describing the app (name, icons, start URL, display mode) to make it installable.</li> + <li><strong>HTTPS:</strong> Required for Service Workers and other PWA features.</li> + </ul> + <h6>Benefits</h6> + <ul> + <li><strong>Reliable:</strong> Load instantly, even in uncertain network conditions.</li> + <li><strong>Fast:</strong> Respond quickly to user interactions.</li> + <li><strong>Engaging:</strong> Feel like a native app, installable, push notifications.</li> + </ul> + </div> + </div> + </div> + </div> <!-- /.row --> + </div> <!-- /.schema-container --> + + <!-- VIII. Key Considerations for Frontend Developers --> + <div class="schema-container section-arch" data-section-id="section-arch" data-section-name="Architecture"> + <h2 class="section-title" id="section-arch-title">Key Considerations for Frontend Developers & Architects</h2> + <div class="row"> + <div class="col-12"> + <div class="info-card card-arch" id="card-arch-summary"> + <div class="card-body"> + <h5 class="text-center"><i class="bi bi-building-gear" aria-hidden="true"></i> Architectural Decision Points</h5> + <div class="card-content-wrapper"> + <p class="summary text-center">Key choices when building frontend applications: selecting <span class="term">frameworks/libraries</span>, defining <span class="term">state management</span> strategy, choosing <span class="term">build tools</span>, implementing <span class="term">testing</span>, managing <span class="term">performance</span>, ensuring <span class="term">compatibility</span> & <span class="term">accessibility</span>, and optimizing <span class="term">developer experience (DX)</span>. <a href="https://roadmap.sh/frontend" target="_blank" rel="noopener noreferrer" data-bs-toggle="tooltip" title="External link: Frontend Developer Roadmap">Frontend Roadmap</a></p> + <button class="btn btn-sm details-toggle mx-auto" type="button" data-bs-toggle="collapse" data-bs-target="#collapseArchConsiderations" aria-expanded="false" aria-controls="collapseArchConsiderations"> + Explore Further <i class="bi bi-chevron-down"></i> + </button> + </div> + </div> + <div class="collapse collapse-content" id="collapseArchConsiderations"> + <h6>Core Considerations</h6> + <ul> + <li><strong>Framework/Library Choice:</strong> React, Vue, Angular, Svelte, or none? Based on team expertise, project scale, performance needs, ecosystem support, community.</li> + <li><strong>State Management:</strong> Local state, Context API, Redux, Zustand, Pinia, NgRx etc. Depends on application complexity, data flow patterns, and team preference.</li> + <li><strong>Build Tooling:</strong> Vite, Webpack, Parcel? Configuration complexity vs. build speed, dev server experience (HMR), plugin ecosystem.</li> + <li><strong>Testing Strategy:</strong> Levels of testing (unit, integration, component, E2E), chosen tools, target code coverage, testing pyramid/trophy.</li> + <li><strong>Performance Budget:</strong> Defining metrics (Core Web Vitals: LCP, FID/INP, CLS), bundle size limits, load times. Strategies for optimization.</li> + <li><strong>Cross-Browser/Device Compatibility:</strong> Target browsers/devices, testing approach, polyfills, progressive enhancement vs. graceful degradation.</li> + <li><strong>Accessibility (a11y):</strong> Integrating accessibility from the design phase through development and testing. Adherence to WCAG guidelines.</li> + <li><strong>SEO:</strong> Impact of rendering strategy (CSR, SSR, SSG, ISR). Frameworks like Next.js, Nuxt.js, SvelteKit often assist here.</li> + <li><strong>Developer Experience (DX):</strong> Tooling setup, HMR speed, linting/formatting, documentation, monorepo vs. polyrepo.</li> + <li><strong>TypeScript vs JavaScript:</strong> Trade-offs between static typing benefits (maintainability, early error detection) and potential development overhead/learning curve.</li> + <li><strong>Monorepo vs. Polyrepo:</strong> Code organization strategy for larger projects or multiple related applications/libraries.</li> + <li><strong>Data Fetching Strategy:</strong> REST, GraphQL, gRPC? Client-side fetching, server components, dedicated data fetching libraries (React Query, SWR).</li> + </ul> + <p>These decisions significantly impact maintainability, scalability, performance, security, and team productivity over the lifecycle of the application.</p> + </div> + </div> + </div> + </div> <!-- /.row --> + </div> <!-- /.schema-container --> + + +</div> <!-- /container#main-container --> + +<footer class="container text-center pb-3"> + <p class="mb-1">© <span id="currentYear"></span> David Veksler Cheatsheets</p> + <p class="mb-2" style="font-size: 0.8em;">Last Updated: <span id="lastUpdatedDate">May 12, 2025</span></p> + <div> + <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript" title="External link: MDN JavaScript Guide" target="_blank" rel="noopener noreferrer" class="mx-2 link-secondary" data-bs-toggle="tooltip" data-bs-placement="top"> + <i class="bi bi-book" aria-hidden="true"></i> MDN JS Docs + </a> + <a href="https://react.dev/" title="External link: Official React Documentation" target="_blank" rel="noopener noreferrer" class="mx-2 link-secondary" data-bs-toggle="tooltip" data-bs-placement="top"> + <i class="bi bi-gem" aria-hidden="true"></i> React Docs + </a> + <a href="https://web.dev/" title="External link: web.dev by Google" target="_blank" rel="noopener noreferrer" class="mx-2 link-secondary" data-bs-toggle="tooltip" data-bs-placement="top"> + <i class="bi bi-google" aria-hidden="true"></i> web.dev + </a> + <a href="https://roadmap.sh/frontend" title="External link: Frontend Developer Roadmap" target="_blank" rel="noopener noreferrer" class="mx-2 link-secondary" data-bs-toggle="tooltip" data-bs-placement="top"> + <i class="bi bi-map" aria-hidden="true"></i> Frontend Roadmap + </a> + </div> + + <div> + <a href="https://www.linkedin.com/in/davidveksler/" title="External link: David Veksler on LinkedIn" target="_blank" rel="noopener noreferrer" class="mx-2 link-secondary" data-bs-toggle="tooltip" data-bs-placement="top"> + <i class="bi bi-linkedin" aria-hidden="true"></i> LinkedIn + </a> + <a href="https://cheatsheets.davidveksler.com/" title="External link: Browse All Cheatsheets by David Veksler" class="mx-2 link-secondary" data-bs-toggle="tooltip" data-bs-placement="top"> + <i class="bi bi-collection" aria-hidden="true"></i> All Cheatsheets + </a> + </div> +</footer> + +<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script> +<script> +document.addEventListener('DOMContentLoaded', () => { + const mainContainer = document.getElementById('main-container'); + const searchBox = document.getElementById('search-box'); + const categoryFiltersContainer = document.getElementById('category-filters'); + const noResultsDiv = document.getElementById('no-results'); + const allSchemaContainers = Array.from(document.querySelectorAll('.schema-container')); + const allInfoCards = Array.from(document.querySelectorAll('.info-card')); + + let currentHoverState = { card: null, line: null }; + let activeFilter = 'all'; // To store the currently active category filter + + // Initialize Bootstrap Tooltips + const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]'); + const tooltipList = [...tooltipTriggerList].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl)); + + + // --- Initialize Filters & Search --- + function initializeFiltersAndSearch() { + // Create filter buttons + const allButton = document.createElement('button'); + allButton.type = 'button'; + allButton.classList.add('btn', 'btn-outline-secondary', 'filter-btn', 'active'); + allButton.textContent = 'All Categories'; + allButton.dataset.filter = 'all'; + allButton.setAttribute('data-bs-toggle', 'tooltip'); + allButton.setAttribute('data-bs-placement', 'top'); + allButton.setAttribute('title', 'Show all categories'); + categoryFiltersContainer.appendChild(allButton); + new bootstrap.Tooltip(allButton); + + const btnGroup = document.createElement('div'); + btnGroup.classList.add('btn-group', 'flex-wrap'); + btnGroup.setAttribute('role', 'group'); + + allSchemaContainers.forEach(section => { + const sectionId = section.dataset.sectionId; + // Use data-section-name directly if available and accurate + const sectionName = section.dataset.sectionName || section.querySelector('.section-title').textContent.trim().replace(' Features (ES6+)', '').replace(' Fundamentals', '').replace(' Environment & Web APIs','').replace(' & Libraries','').replace(' Patterns & Libraries','').replace(' Ecosystem & Tooling','').replace(' Concepts & Patterns','').replace(' Considerations for Frontend Developers & Architects',''); + const button = document.createElement('button'); + button.type = 'button'; + button.classList.add('btn', 'btn-outline-secondary', 'filter-btn'); + button.textContent = sectionName; + button.dataset.filter = sectionId; + button.setAttribute('data-bs-toggle', 'tooltip'); + button.setAttribute('data-bs-placement', 'top'); + button.setAttribute('title', `Filter by ${sectionName}`); + btnGroup.appendChild(button); + new bootstrap.Tooltip(button); + }); + categoryFiltersContainer.appendChild(btnGroup); + + // Event listener for search box + searchBox.addEventListener('input', () => { + applyFiltersAndSearch(); + // No line repositioning needed on search input usually, unless layout shifts drastically + }); + + // Event listener for filter buttons (using event delegation) + categoryFiltersContainer.addEventListener('click', (event) => { + if (event.target.classList.contains('filter-btn')) { + document.querySelectorAll('#category-filters .filter-btn').forEach(btn => btn.classList.remove('active')); + event.target.classList.add('active'); + activeFilter = event.target.dataset.filter; + applyFiltersAndSearch(); + clearHoverState(true); // Clear lines when filtering + setTimeout(positionLines, 50); // Allow DOM changes to settle before repositioning if needed + } + }); + } + + function applyFiltersAndSearch() { + const searchTerm = searchBox.value.toLowerCase().trim(); + let itemsFound = 0; + let sectionsWithVisibleItems = 0; + + allSchemaContainers.forEach(section => { + const sectionId = section.dataset.sectionId; + let sectionHasVisibleCards = false; + + const cardsInSection = Array.from(section.querySelectorAll('.info-card')); + + cardsInSection.forEach(card => { + const cardTitle = card.querySelector('h5') ? card.querySelector('h5').textContent.toLowerCase() : ''; + const cardSummary = card.querySelector('p.summary') ? card.querySelector('p.summary').textContent.toLowerCase() : ''; + const cardDetailsCollapse = card.querySelector('.collapse-content'); + // Include detail text only if it's not just a placeholder comment + const cardDetailsText = (cardDetailsCollapse && !cardDetailsCollapse.textContent.includes('<!-- Detailed content needed -->') && !cardDetailsCollapse.textContent.includes('Content placeholder for')) ? cardDetailsCollapse.textContent.toLowerCase() : ''; + const versionTag = card.querySelector('.version-tag') ? card.querySelector('.version-tag').textContent.toLowerCase() : ''; + + // Include data-keywords if you add them to cards + // const keywords = card.dataset.keywords ? card.dataset.keywords.toLowerCase() : ''; + + const cardTextContent = `${cardTitle} ${cardSummary} ${cardDetailsText} ${versionTag}`; // Add keywords here if used + + const matchesSearch = searchTerm === '' || cardTextContent.includes(searchTerm); + const matchesFilter = activeFilter === 'all' || sectionId === activeFilter; + + const column = card.closest('.col-lg-4.col-md-6'); // Get parent column + + if (matchesSearch && matchesFilter) { + if(column) column.style.display = ''; // Show column + // card.style.display = 'flex'; // Card display is handled by column + sectionHasVisibleCards = true; + itemsFound++; + } else { + if(column) column.style.display = 'none'; // Hide column + // card.style.display = 'none'; + } + }); + + // Show/hide entire section based on filter and if it has visible cards + if ((activeFilter === 'all' || sectionId === activeFilter) && sectionHasVisibleCards) { + section.style.display = ''; + sectionsWithVisibleItems++; + } else if (searchTerm !== '' && (activeFilter === 'all' || sectionId === activeFilter) && !sectionHasVisibleCards) { + // Section matches filter, but no cards match search, so hide section + section.style.display = 'none'; + } + else if (activeFilter !== 'all' && sectionId !== activeFilter) { + // Section does not match filter + section.style.display = 'none'; + } else if (searchTerm === '' && activeFilter === 'all') { + // No search, all filter, show if it has cards (already handled by sectionHasVisibleCards) + section.style.display = sectionHasVisibleCards ? '' : 'none'; + } else if (searchTerm === '' && sectionId === activeFilter) { + // No search, specific filter, show if it has cards (already handled) + section.style.display = sectionHasVisibleCards ? '' : 'none'; + } + }); + + noResultsDiv.style.display = itemsFound === 0 && (searchTerm !== '' || activeFilter !== 'all') ? 'block' : 'none'; + } + + + // --- LeaderLine Drawing Logic --- + function debounce(func, wait) { + let timeout; + return function executedFunction(...args) { + const later = () => { + clearTimeout(timeout); + func(...args); + }; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + }; + } + + function getElementColor(element) { + if (!element) return '#6c757d'; // Default tooling color + // Get color directly from the element first (for framework overrides) + let color = window.getComputedStyle(element).getPropertyValue('--db-category-color').trim(); + // If not set directly or invalid, try the parent section + if (!color || color === 'initial' || color === 'inherit' || color === 'var(--js-color-frameworks)') { // Check against default framework color too + const section = element.closest('.schema-container'); + if (section) { + color = window.getComputedStyle(section).getPropertyValue('--db-category-color').trim(); + } + } + return color || '#6c757d'; // Fallback to default + } + + + function clearHoverState(forceClear = false) { + const isMouseStillOverCard = !forceClear && currentHoverState.card && currentHoverState.card.matches(':hover'); + + if (forceClear || !isMouseStillOverCard) { + if (currentHoverState.line) { + try { currentHoverState.line.remove(); } catch (e) { /* Ignore error if line already gone */ } + currentHoverState.line = null; + } + if (currentHoverState.card) { + currentHoverState.card.classList.remove('is-highlighted'); + currentHoverState.card = null; + } + } + } + + function applyHoverState(card) { + if (!card || card === currentHoverState.card || card.style.display === 'none') return; + + clearHoverState(true); + + const schemaContainer = card.closest('.schema-container'); + const sectionHeader = schemaContainer ? schemaContainer.querySelector('.section-title') : null; + + const canDrawLine = sectionHeader && card.id && sectionHeader.id && + sectionHeader.offsetParent !== null && card.offsetParent !== null && + typeof LeaderLine !== 'undefined'; + + currentHoverState.card = card; + card.classList.add('is-highlighted'); + + if (canDrawLine) { + try { + const cardColor = getElementColor(card); + const line = new LeaderLine( + sectionHeader, card, + { + color: cardColor, size: 2.5, path: 'fluid', + startSocket: 'bottom', endSocket: 'top', + startSocketGravity: [0, -25], endSocketGravity: [0, 25], + dash: { animation: true, len: 8, gap: 4 }, + } + ); + currentHoverState.line = line; + } catch (e) { + console.error("LeaderLine error:", e); + clearHoverState(true); + } + } + } + + mainContainer.addEventListener('mouseover', (event) => { + const targetCard = event.target.closest('.info-card'); + const column = targetCard ? targetCard.closest('.col-lg-4.col-md-6') : null; + if (targetCard && column && column.style.display !== 'none' && targetCard !== currentHoverState.card) { + applyHoverState(targetCard); + } + }); + + mainContainer.addEventListener('mouseout', (event) => { + const currentCard = currentHoverState.card; + if (currentCard && event.target.closest('.info-card') === currentCard) { + const relatedTarget = event.relatedTarget; + if (!currentCard.contains(relatedTarget) && (!relatedTarget || !relatedTarget.closest('.info-card'))) { + setTimeout(() => { + if (!currentCard.matches(':hover')) { + clearHoverState(false); + } + }, 50); + } + } + }); + + const positionLines = debounce(() => { + if (currentHoverState.line) { + try { + if (currentHoverState.line && typeof currentHoverState.line.position === 'function') { + const startElem = currentHoverState.line.start; + const endElem = currentHoverState.line.end; + if (startElem && endElem && document.body.contains(startElem) && document.body.contains(endElem) && + startElem.offsetParent !== null && endElem.offsetParent !== null) { + currentHoverState.line.position(); + } else { + clearHoverState(true); + } + } else { + clearHoverState(true); + } + } catch (e) { + console.warn("Reposition error:", e); + clearHoverState(true); + } + } + }, 100); + + window.addEventListener('resize', positionLines); + window.addEventListener('scroll', positionLines, { passive: true }); + + // --- Collapse Handling --- + const collapseElements = document.querySelectorAll('.collapse'); + collapseElements.forEach(collapseEl => { + const button = document.querySelector(`.details-toggle[data-bs-target="#${collapseEl.id}"]`); + const iconEl = button ? button.querySelector('.bi') : null; + + if (button && iconEl) { + const updateIconState = () => { + if (collapseEl.classList.contains('show')) { + iconEl.classList.remove('bi-chevron-down'); iconEl.classList.add('bi-chevron-up'); + button.setAttribute('aria-expanded', 'true'); + } else { + iconEl.classList.remove('bi-chevron-up'); iconEl.classList.add('bi-chevron-down'); + button.setAttribute('aria-expanded', 'false'); + } + }; + updateIconState(); + + collapseEl.addEventListener('show.bs.collapse', () => { updateIconState(); setTimeout(positionLines, 50); }); + collapseEl.addEventListener('shown.bs.collapse', positionLines); + collapseEl.addEventListener('hide.bs.collapse', () => { updateIconState(); setTimeout(positionLines, 50); }); + collapseEl.addEventListener('hidden.bs.collapse', positionLines); + } + }); + + // --- Footer Year --- + document.getElementById('currentYear').textContent = new Date().getFullYear(); + + // --- Initial Setup --- + initializeFiltersAndSearch(); + applyFiltersAndSearch(); +}); +</script> +</body> +</html> \ No newline at end of file