bhylu.com

Advertisements

jQuery Event Delegation

Delegate from a stable feature root and identify the matched control rather than an arbitrary inner click target.

How it works

A delegated handler sits on a stable ancestor and responds when an event bubbles from a matching descendant. It can handle rows inserted later without rebinding each button. Keep the root close to the feature rather than delegating every action from document. The example starts with an empty list, adds a safe text button and then selects it through the existing delegated handler.

Run in a separate local browser lab

Save this complete HTML source as index.html in an empty folder. Put the pinned full jQuery 4.0.0 file beside it and preserve the MIT licence notice. The document includes its own CSS and JavaScript. Bhylu’s shared website theme does not load jQuery globally.

Open index.html directly in a normal browser. You may also use the optional loopback fixture server with Node 22 if you want the same HTTP setup as the network lessons.

jQuery examples do not run in Bhylu’s current playground: it blocks external libraries and network access. No Apache, MySQL or website configuration change is needed. Review the full-build setup before using Ajax, effects or plugins.

Example

index.html

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>jQuery Handle Rows Added After Initialization</title>
    <style>
      :root {
        font:
          18px/1.6 system-ui,
          sans-serif;
        color: #16304e;
        background: #fff;
        color-scheme: light;
      }
      * {
        box-sizing: border-box;
      }
      body {
        margin: 0;
      }
      main {
        max-width: 50rem;
        margin: auto;
        padding: 1.25rem;
      }
      h1 {
        font-size: 1.8rem;
        line-height: 1.2;
      }
      h2 {
        font-size: 1.3rem;
      }
      button,
      input,
      select,
      textarea {
        font: inherit;
        max-width: 100%;
      }
      button {
        margin: 0.2rem;
        padding: 0.4rem 0.7rem;
        background: #034fa0;
        color: white;
        border: 1px solid #034fa0;
        border-radius: 0.3rem;
      }
      button:disabled {
        opacity: 0.6;
      }
      label {
        display: block;
        margin: 0.5rem 0;
      }
      input:not([type='checkbox']),
      select,
      textarea {
        display: block;
        padding: 0.3rem;
      }
      a {
        color: #034fa0;
      }
      output {
        display: block;
      }
      article,
      section,
      fieldset {
        padding: 0.75rem;
        margin-block: 0.75rem;
        border: 1px solid #a9bcd1;
      }
      ul {
        padding-left: 1.5rem;
      }
      :focus-visible {
        outline: 3px solid #0078d4;
        outline-offset: 3px;
      }
      .chosen {
        border: 3px solid #0078d4;
      }
      .highlight {
        font-weight: 700;
      }
      .muted {
        opacity: 0.7;
      }
      pre {
        white-space: pre-wrap;
        overflow-wrap: anywhere;
      }
      :root[data-theme='dark'] {
        color: #d6e7fb;
        background: #061d30;
        color-scheme: dark;
      }
      :root[data-theme='dark'] a {
        color: #8ecbff;
      }
    </style>
  </head>
  <body>
    <main>
      <h1>Neighbourhood book swap</h1>
      <button id="add">Add local title</button>
      <ul id="books"></ul>
      <output>No title chosen</output>
    </main>
    <script src="jquery.min.js"></script>
    <script>
      jQuery(function ($) {
        $('#books').on('click.swap', '.choose', function () {
          $('output').text('Local choice: ' + $(this).text());
        });
        $('#add').on('click', function () {
          $('<li>')
            .append($('<button>').addClass('choose').text('Evening Stories'))
            .appendTo('#books');
        });
      });
    </script>
  </body>
</html>

Expected result

The newly added Evening Stories button works immediately and reports a local choice.

The delegated selector matches the button as the event reaches the root; this is not necessarily the deepest event.target if the button contains an icon. Some events have special delegation semantics, so consult their contracts rather than assuming every browser event bubbles identically. Namespacing the handler prepares a targeted teardown. The row title is assigned as text rather than interpolated HTML.

Use jQuery’s official API documentation for exact method and return contracts.

Advertisements