{ "$schema": "../schemas/code-crispies-module-schema.json", "id": "js-events", "title": "JS Events", "description": "Learn to respond to user actions by adding event listeners for clicks, toggling classes, and updating the page dynamically.", "mode": "javascript", "difficulty": "beginner", "lessons": [ { "id": "js-click", "title": "Click Handler", "description": "Use addEventListener(\"click\", ...) to run code when an element is clicked. The first argument is the event type and the second is a callback function.", "task": "Add a click event listener to btn that sets out.textContent to \"Clicked!\"", "previewHTML": "\n

Waiting...

", "previewBaseCSS": "body { font-family: system-ui, sans-serif; padding: 1rem; }", "sandboxCSS": "", "initialCode": "", "solution": "btn.addEventListener(\"click\", () => {\n out.textContent = \"Clicked!\";\n});", "codePrefix": "const btn = document.querySelector(\"#btn\");\nconst out = document.querySelector(\"#out\");\n", "codeSuffix": "", "previewContainer": "preview-area", "validations": [ { "type": "contains", "value": "addEventListener", "message": "Use addEventListener to listen for events" }, { "type": "regex", "value": "addEventListener\\s*\\(\\s*[\"']click[\"']", "message": "Listen for the \"click\" event" }, { "type": "regex", "value": "textContent\\s*=\\s*[\"']Clicked![\"']", "message": "Set out.textContent to \"Clicked!\" inside the handler" } ] }, { "id": "js-toggle", "title": "Toggle a Class", "description": "Use classList.toggle() to add a class if it's missing or remove it if it's present. This is perfect for on/off states like toggling dark mode or active states.", "task": "Inside the click handler, call box.classList.toggle(\"on\")", "previewHTML": "
\n", "previewBaseCSS": "body { font-family: system-ui, sans-serif; padding: 1rem; }", "sandboxCSS": "", "initialCode": "", "solution": "box.addEventListener(\"click\", () => {\n box.classList.toggle(\"on\");\n});", "codePrefix": "const box = document.querySelector(\"#box\");\n", "codeSuffix": "", "previewContainer": "preview-area", "validations": [ { "type": "contains", "value": "classList.toggle", "message": "Use classList.toggle() to toggle the class" }, { "type": "regex", "value": "classList\\.toggle\\s*\\(\\s*[\"']on[\"']\\s*\\)", "message": "Toggle the class \"on\"" }, { "type": "contains", "value": "addEventListener", "message": "Use addEventListener to listen for clicks" } ] }, { "id": "js-counter", "title": "Simple Counter", "description": "Combine variables and event listeners to build interactive features. Use let for a value that changes, and update the display each time the button is clicked.", "task": "In the click handler, increment count by 1 and set out.textContent to count", "previewHTML": "\n

0

", "previewBaseCSS": "body { font-family: system-ui, sans-serif; padding: 1rem; }", "sandboxCSS": "", "initialCode": "", "solution": "btn.addEventListener(\"click\", () => {\n count++;\n out.textContent = count;\n});", "codePrefix": "const btn = document.querySelector(\"#btn\");\nconst out = document.querySelector(\"#out\");\nlet count = 0;\n", "codeSuffix": "", "previewContainer": "preview-area", "validations": [ { "type": "contains", "value": "addEventListener", "message": "Use addEventListener to listen for clicks" }, { "type": "regex", "value": "count\\s*\\+\\+|count\\s*\\+=\\s*1|count\\s*=\\s*count\\s*\\+\\s*1", "message": "Increment count by 1 (use count++)" }, { "type": "regex", "value": "out\\.textContent\\s*=\\s*count", "message": "Update the display with out.textContent = count" } ] } ] }