bhylu.com

Advertisements

jQuery Plugins

Extend the collection API only when a reusable feature has a clear input and ownership boundary.

How it works

A jQuery plugin commonly adds a method to $.fn and returns the original collection so callers can keep chaining. The method should document its accepted options and its effects on each matched element. This example defines a tiny emphasis operation with an explicit boolean option. It is a local teaching plugin, not an imported third-party dependency. Keeping the contract narrow makes invalid input and collection behaviour easier to review.

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 Give a Plugin a Small Chainable Contract</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>
      <p class="book">River Paths</p>
      <p class="book">Small Gardens</p>
      <output></output>
    </main>
    <script src="jquery.min.js"></script>
    <script>
      jQuery(function ($) {
        $.fn.swapEmphasis = function (options = {}) {
          const active = options.active ?? true;
          if (typeof active !== 'boolean')
            throw new TypeError('active must be boolean');
          return this.each(function () {
            $(this).toggleClass('highlight', active);
          });
        };
        $('.book').swapEmphasis({ active: true }).attr('data-reviewed', 'yes');
        $('output').text($('.book.highlight').length + ' emphasized books');
      });
    </script>
  </body>
</html>

Expected result

Both books are emphasized and still accept the chained attribute setter.

The each call preserves per-element context while returning the collection. Choose a distinctive method name to avoid collisions with existing plugins. A real plugin may need private state, event namespacing and teardown, which the next lesson adds. Do not accept arbitrary method names or executable strings as a flexible configuration shortcut.

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

Advertisements