javascript

examples

examples.js
/**
 * ============================================================
 * 10.3 Events and Event Handling - Examples
 * ============================================================
 *
 * This file demonstrates various event handling techniques
 * including event listeners, event object, and propagation.
 *
 * To run these examples:
 * 1. Create an HTML file with appropriate elements
 * 2. Link this script or paste into browser console
 */

// =============================================================
// EXAMPLE 1: Basic Event Listener
// =============================================================
console.log('=== Example 1: Basic Event Listener ===');

const button1 = document.getElementById('button1');

if (button1) {
  button1.addEventListener('click', function () {
    console.log('Button clicked!');
  });

  console.log('Click event listener added to button1');
}

// =============================================================
// EXAMPLE 2: Named Function Handler
// =============================================================
console.log('\n=== Example 2: Named Function Handler ===');

function handleButtonClick(event) {
  console.log('Button clicked at:', event.timeStamp);
  console.log('Button text:', event.target.textContent);
}

const button2 = document.getElementById('button2');
if (button2) {
  button2.addEventListener('click', handleButtonClick);
  console.log('Named function handler attached');
}

// =============================================================
// EXAMPLE 3: Arrow Function Handler
// =============================================================
console.log('\n=== Example 3: Arrow Function Handler ===');

const button3 = document.getElementById('button3');

if (button3) {
  button3.addEventListener('click', (event) => {
    console.log('Arrow function handled click');
    console.log('Event type:', event.type);
  });
}

// =============================================================
// EXAMPLE 4: Removing Event Listeners
// =============================================================
console.log('\n=== Example 4: Removing Event Listeners ===');

const button4 = document.getElementById('button4');

function oneTimeHandler() {
  console.log('This runs only once!');
  button4.removeEventListener('click', oneTimeHandler);
  console.log('Handler removed');
}

if (button4) {
  button4.addEventListener('click', oneTimeHandler);
  console.log('Click to run once, then handler will be removed');
}

// =============================================================
// EXAMPLE 5: Using { once: true } Option
// =============================================================
console.log('\n=== Example 5: Using { once: true } Option ===');

const button5 = document.getElementById('button5');

if (button5) {
  button5.addEventListener(
    'click',
    () => {
      console.log('This automatically runs only once!');
    },
    { once: true }
  );
}

// =============================================================
// EXAMPLE 6: Multiple Handlers on Same Element
// =============================================================
console.log('\n=== Example 6: Multiple Handlers on Same Element ===');

const button6 = document.getElementById('button6');

if (button6) {
  button6.addEventListener('click', () => {
    console.log('Handler 1: Logging click');
  });

  button6.addEventListener('click', () => {
    console.log('Handler 2: Updating UI');
  });

  button6.addEventListener('click', () => {
    console.log('Handler 3: Sending analytics');
  });

  console.log('Three handlers attached to same button');
}

// =============================================================
// EXAMPLE 7: Event Object Properties
// =============================================================
console.log('\n=== Example 7: Event Object Properties ===');

const infoBox = document.getElementById('infoBox');

if (infoBox) {
  infoBox.addEventListener('click', (event) => {
    console.log('=== Event Object ===');
    console.log('type:', event.type);
    console.log('target:', event.target);
    console.log('currentTarget:', event.currentTarget);
    console.log('timeStamp:', event.timeStamp);
    console.log('isTrusted:', event.isTrusted);
  });
}

// =============================================================
// EXAMPLE 8: Mouse Position Properties
// =============================================================
console.log('\n=== Example 8: Mouse Position Properties ===');

const trackingArea = document.getElementById('trackingArea');

if (trackingArea) {
  trackingArea.addEventListener('mousemove', (event) => {
    console.log('clientX/Y (viewport):', event.clientX, event.clientY);
    console.log('pageX/Y (document):', event.pageX, event.pageY);
    console.log('offsetX/Y (element):', event.offsetX, event.offsetY);
    console.log('screenX/Y (screen):', event.screenX, event.screenY);
  });

  console.log('Move mouse over trackingArea to see coordinates');
}

// =============================================================
// EXAMPLE 9: Mouse Button Detection
// =============================================================
console.log('\n=== Example 9: Mouse Button Detection ===');

const clickArea = document.getElementById('clickArea');

if (clickArea) {
  clickArea.addEventListener('mousedown', (event) => {
    const buttons = ['Left', 'Middle', 'Right'];
    console.log('Button pressed:', buttons[event.button]);
    console.log('Button code:', event.button);
  });

  // Prevent context menu for right-click demo
  clickArea.addEventListener('contextmenu', (e) => e.preventDefault());
}

// =============================================================
// EXAMPLE 10: Keyboard Events
// =============================================================
console.log('\n=== Example 10: Keyboard Events ===');

const textInput = document.getElementById('textInput');

if (textInput) {
  textInput.addEventListener('keydown', (event) => {
    console.log('Key down:', event.key);
    console.log('Code:', event.code);
    console.log(
      'Modifiers - Shift:',
      event.shiftKey,
      'Ctrl:',
      event.ctrlKey,
      'Alt:',
      event.altKey
    );
  });

  textInput.addEventListener('keyup', (event) => {
    console.log('Key up:', event.key);
  });
}

// =============================================================
// EXAMPLE 11: Keyboard Shortcuts
// =============================================================
console.log('\n=== Example 11: Keyboard Shortcuts ===');

document.addEventListener('keydown', (event) => {
  // Ctrl + S
  if (event.ctrlKey && event.key === 's') {
    event.preventDefault();
    console.log('Save shortcut triggered!');
  }

  // Ctrl + Shift + F
  if (event.ctrlKey && event.shiftKey && event.key === 'F') {
    event.preventDefault();
    console.log('Find/Replace shortcut triggered!');
  }

  // Escape key
  if (event.key === 'Escape') {
    console.log('Escape pressed - close modal');
  }
});

console.log('Try: Ctrl+S, Ctrl+Shift+F, or Escape');

// =============================================================
// EXAMPLE 12: Event Bubbling
// =============================================================
console.log('\n=== Example 12: Event Bubbling ===');

// HTML: <div id="outer"><div id="middle"><div id="inner">Click</div></div></div>
const outer = document.getElementById('outer');
const middle = document.getElementById('middle');
const inner = document.getElementById('inner');

if (outer && middle && inner) {
  outer.addEventListener('click', () => {
    console.log('3. Outer div clicked (bubbled up)');
  });

  middle.addEventListener('click', () => {
    console.log('2. Middle div clicked (bubbled up)');
  });

  inner.addEventListener('click', () => {
    console.log('1. Inner div clicked (target)');
  });

  console.log('Click the inner element to see bubbling');
}

// =============================================================
// EXAMPLE 13: Event Capturing
// =============================================================
console.log('\n=== Example 13: Event Capturing ===');

const captureOuter = document.getElementById('captureOuter');
const captureInner = document.getElementById('captureInner');

if (captureOuter && captureInner) {
  captureOuter.addEventListener(
    'click',
    () => {
      console.log('1. Outer (capture phase)');
    },
    { capture: true }
  );

  captureOuter.addEventListener('click', () => {
    console.log('3. Outer (bubble phase)');
  });

  captureInner.addEventListener('click', () => {
    console.log('2. Inner (target phase)');
  });

  console.log('Click inner to see: capture → target → bubble');
}

// =============================================================
// EXAMPLE 14: target vs currentTarget
// =============================================================
console.log('\n=== Example 14: target vs currentTarget ===');

const container = document.getElementById('container');

if (container) {
  container.addEventListener('click', (event) => {
    console.log('target (what was clicked):', event.target.tagName);
    console.log(
      'currentTarget (listener element):',
      event.currentTarget.tagName
    );
    console.log('Are they equal?', event.target === event.currentTarget);
  });
}

// =============================================================
// EXAMPLE 15: preventDefault
// =============================================================
console.log('\n=== Example 15: preventDefault ===');

const link = document.getElementById('preventedLink');

if (link) {
  link.addEventListener('click', (event) => {
    event.preventDefault();
    console.log('Link click prevented!');
    console.log('Would have gone to:', link.href);
  });
}

const form = document.getElementById('preventedForm');

if (form) {
  form.addEventListener('submit', (event) => {
    event.preventDefault();
    console.log('Form submission prevented!');
    const formData = new FormData(form);
    console.log('Form data:', Object.fromEntries(formData));
  });
}

// =============================================================
// EXAMPLE 16: stopPropagation
// =============================================================
console.log('\n=== Example 16: stopPropagation ===');

const stopOuter = document.getElementById('stopOuter');
const stopInner = document.getElementById('stopInner');

if (stopOuter && stopInner) {
  stopOuter.addEventListener('click', () => {
    console.log('Outer clicked');
  });

  stopInner.addEventListener('click', (event) => {
    event.stopPropagation();
    console.log('Inner clicked - propagation stopped!');
  });

  console.log('Click inner: only inner handler runs');
  console.log('Click outer: outer handler runs');
}

// =============================================================
// EXAMPLE 17: stopImmediatePropagation
// =============================================================
console.log('\n=== Example 17: stopImmediatePropagation ===');

const multiHandler = document.getElementById('multiHandler');

if (multiHandler) {
  multiHandler.addEventListener('click', (event) => {
    console.log('Handler 1 runs');
    event.stopImmediatePropagation();
  });

  multiHandler.addEventListener('click', () => {
    console.log('Handler 2 - never runs!');
  });

  multiHandler.addEventListener('click', () => {
    console.log('Handler 3 - never runs!');
  });
}

// =============================================================
// EXAMPLE 18: Mouse Enter/Leave Events
// =============================================================
console.log('\n=== Example 18: Mouse Enter/Leave Events ===');

const hoverBox = document.getElementById('hoverBox');

if (hoverBox) {
  // mouseenter/mouseleave - don't bubble
  hoverBox.addEventListener('mouseenter', () => {
    console.log('Mouse entered (no bubble)');
    hoverBox.style.backgroundColor = 'lightblue';
  });

  hoverBox.addEventListener('mouseleave', () => {
    console.log('Mouse left (no bubble)');
    hoverBox.style.backgroundColor = '';
  });
}

// =============================================================
// EXAMPLE 19: Focus and Blur Events
// =============================================================
console.log('\n=== Example 19: Focus and Blur Events ===');

const focusInput = document.getElementById('focusInput');

if (focusInput) {
  focusInput.addEventListener('focus', () => {
    console.log('Input focused');
    focusInput.style.borderColor = 'blue';
  });

  focusInput.addEventListener('blur', () => {
    console.log('Input blurred');
    focusInput.style.borderColor = '';
  });
}

// =============================================================
// EXAMPLE 20: Input and Change Events
// =============================================================
console.log('\n=== Example 20: Input and Change Events ===');

const liveInput = document.getElementById('liveInput');

if (liveInput) {
  // Input fires on every keystroke
  liveInput.addEventListener('input', (event) => {
    console.log('Input event - current value:', event.target.value);
  });

  // Change fires when input loses focus
  liveInput.addEventListener('change', (event) => {
    console.log('Change event - final value:', event.target.value);
  });
}

// =============================================================
// EXAMPLE 21: Double Click
// =============================================================
console.log('\n=== Example 21: Double Click ===');

const dblClickBox = document.getElementById('dblClickBox');

if (dblClickBox) {
  dblClickBox.addEventListener('click', () => {
    console.log('Single click detected');
  });

  dblClickBox.addEventListener('dblclick', () => {
    console.log('Double click detected!');
  });
}

// =============================================================
// EXAMPLE 22: Scroll Events
// =============================================================
console.log('\n=== Example 22: Scroll Events ===');

const scrollBox = document.getElementById('scrollBox');

if (scrollBox) {
  scrollBox.addEventListener('scroll', () => {
    console.log('Scroll position:', scrollBox.scrollTop);
  });
}

// Window scroll (throttled for performance)
let scrollTimeout;
window.addEventListener(
  'scroll',
  () => {
    if (!scrollTimeout) {
      scrollTimeout = setTimeout(() => {
        console.log('Window scrollY:', window.scrollY);
        scrollTimeout = null;
      }, 100);
    }
  },
  { passive: true }
);

// =============================================================
// EXAMPLE 23: Resize Events
// =============================================================
console.log('\n=== Example 23: Resize Events ===');

// Debounced resize handler
let resizeTimeout;
window.addEventListener('resize', () => {
  clearTimeout(resizeTimeout);
  resizeTimeout = setTimeout(() => {
    console.log('Window size:', window.innerWidth, 'x', window.innerHeight);
  }, 250);
});

console.log('Resize window to see dimensions');

// =============================================================
// EXAMPLE 24: Load Events
// =============================================================
console.log('\n=== Example 24: Load Events ===');

// DOM Content Loaded (fires earlier)
document.addEventListener('DOMContentLoaded', () => {
  console.log('DOM fully parsed');
});

// Window load (fires when all resources loaded)
window.addEventListener('load', () => {
  console.log('Page fully loaded (including images, styles)');
});

// Image load
const img = document.getElementById('myImage');
if (img) {
  img.addEventListener('load', () => {
    console.log('Image loaded:', img.src);
  });

  img.addEventListener('error', () => {
    console.log('Image failed to load');
  });
}

// =============================================================
// EXAMPLE 25: Custom Events
// =============================================================
console.log('\n=== Example 25: Custom Events ===');

const customTarget = document.getElementById('customTarget') || document.body;

// Create custom event
const myEvent = new CustomEvent('userAction', {
  bubbles: true,
  cancelable: true,
  detail: {
    action: 'buttonClick',
    timestamp: Date.now(),
    data: { userId: 123 },
  },
});

// Listen for custom event
customTarget.addEventListener('userAction', (event) => {
  console.log('Custom event received!');
  console.log('Action:', event.detail.action);
  console.log('Data:', event.detail.data);
});

// Dispatch custom event
// customTarget.dispatchEvent(myEvent);
console.log('Custom event created. Call: customTarget.dispatchEvent(myEvent)');

// =============================================================
// EXAMPLE 26: Practical - Modal Toggle
// =============================================================
console.log('\n=== Example 26: Practical - Modal Toggle ===');

const modal = document.getElementById('modal');
const openModalBtn = document.getElementById('openModal');
const closeModalBtn = document.getElementById('closeModal');

if (modal && openModalBtn) {
  openModalBtn.addEventListener('click', () => {
    modal.classList.add('open');
    modal.setAttribute('aria-hidden', 'false');
    console.log('Modal opened');
  });

  if (closeModalBtn) {
    closeModalBtn.addEventListener('click', () => {
      modal.classList.remove('open');
      modal.setAttribute('aria-hidden', 'true');
      console.log('Modal closed');
    });
  }

  // Close on backdrop click
  modal.addEventListener('click', (event) => {
    if (event.target === modal) {
      modal.classList.remove('open');
      console.log('Modal closed via backdrop');
    }
  });

  // Close on Escape key
  document.addEventListener('keydown', (event) => {
    if (event.key === 'Escape' && modal.classList.contains('open')) {
      modal.classList.remove('open');
      console.log('Modal closed via Escape');
    }
  });
}

// =============================================================
// EXAMPLE 27: Practical - Drag and Drop
// =============================================================
console.log('\n=== Example 27: Practical - Drag and Drop ===');

const draggable = document.getElementById('draggable');

if (draggable) {
  let isDragging = false;
  let offsetX, offsetY;

  draggable.addEventListener('mousedown', (event) => {
    isDragging = true;
    offsetX = event.clientX - draggable.offsetLeft;
    offsetY = event.clientY - draggable.offsetTop;
    draggable.style.cursor = 'grabbing';
    console.log('Started dragging');
  });

  document.addEventListener('mousemove', (event) => {
    if (!isDragging) return;

    draggable.style.left = event.clientX - offsetX + 'px';
    draggable.style.top = event.clientY - offsetY + 'px';
  });

  document.addEventListener('mouseup', () => {
    if (isDragging) {
      isDragging = false;
      draggable.style.cursor = 'grab';
      console.log('Stopped dragging');
    }
  });
}

// =============================================================
// EXAMPLE 28: Practical - Debounced Search
// =============================================================
console.log('\n=== Example 28: Practical - Debounced Search ===');

const searchInput = document.getElementById('searchInput');

if (searchInput) {
  let debounceTimer;

  searchInput.addEventListener('input', (event) => {
    clearTimeout(debounceTimer);

    debounceTimer = setTimeout(() => {
      const query = event.target.value;
      console.log('Searching for:', query);
      // performSearch(query);
    }, 300);
  });

  console.log('Type in search - fires 300ms after you stop typing');
}

// =============================================================
// EXAMPLE 29: Practical - Form Validation
// =============================================================
console.log('\n=== Example 29: Practical - Form Validation ===');

const validationForm = document.getElementById('validationForm');

if (validationForm) {
  validationForm.addEventListener('submit', (event) => {
    event.preventDefault();

    const inputs = validationForm.querySelectorAll('input[required]');
    let isValid = true;

    inputs.forEach((input) => {
      if (!input.value.trim()) {
        isValid = false;
        input.classList.add('error');
        console.log(`${input.name} is required`);
      } else {
        input.classList.remove('error');
      }
    });

    if (isValid) {
      console.log('Form is valid, submitting...');
    }
  });

  // Clear error on input
  validationForm.addEventListener('input', (event) => {
    if (event.target.value.trim()) {
      event.target.classList.remove('error');
    }
  });
}

// =============================================================
// EXAMPLE 30: Practical - Keyboard Navigation
// =============================================================
console.log('\n=== Example 30: Practical - Keyboard Navigation ===');

const menuItems = document.querySelectorAll('.menu-item');

if (menuItems.length > 0) {
  let currentIndex = 0;

  document.addEventListener('keydown', (event) => {
    if (!['ArrowUp', 'ArrowDown', 'Enter'].includes(event.key)) return;

    event.preventDefault();

    // Remove current highlight
    menuItems[currentIndex].classList.remove('highlighted');

    if (event.key === 'ArrowDown') {
      currentIndex = (currentIndex + 1) % menuItems.length;
    } else if (event.key === 'ArrowUp') {
      currentIndex = (currentIndex - 1 + menuItems.length) % menuItems.length;
    } else if (event.key === 'Enter') {
      console.log('Selected:', menuItems[currentIndex].textContent);
    }

    // Add new highlight
    menuItems[currentIndex].classList.add('highlighted');
    menuItems[currentIndex].focus();
  });
}

// =============================================================
// Summary
// =============================================================
console.log('\n' + '='.repeat(60));
console.log('Examples Summary:');
console.log('='.repeat(60));
console.log('1-6:   Adding and removing event listeners');
console.log('7-11:  Event object properties');
console.log('12-17: Event propagation and control');
console.log('18-24: Common event types');
console.log('25:    Custom events');
console.log('26-30: Practical applications');
console.log('='.repeat(60));
Examples - JavaScript Tutorial | DeepML