made by alan w smith
source socials other projects

bitty

signals based reactivity
non-minified version: bitty-1.1.0-rc1.full.js
Overview

bitty is a web component. It uses signals to make pages reactive. For example:

Waiting for click

The bitty API is made from data-* attributes. For example, here's the HTML that makes up the example:

<bitty-1-1 data-connect="/modules/timestamp-demo.js">
  <button data-send="updateTimestamp">Show Timestamp</button>
  <div data-receive="updateTimestamp">Waiting for click</div>
</bitty-1-1>
<script src="/bitty-1.1.0-rc1.min.js" type="module"></script>

Functionality

The update values from the data-send and data-receive attributes map to a function in the module with the same name.

export default class {
  updateTimestamp(event, element) {
    element.innerHTML = Date().toString();
  }
}

The arguments passed to the function are:

  1. The event that triggered the update (e.g. click events on the button in the example)

  2. The element to update (e.g. the div element in the example)

The event and element are the same ones you'd get from document.addEventListener() and document.querySelector() functions.

When the example button is clicked the div element is passed through the function where it has its innerHTML updated. (The event isn't used in this example.)

Basic Examples

This is a collection of examples showing some of the ways bitty-1-1 can be used. The examples all work. The source code for each is available in the Show Example Code sections.

Send/Receive

Waiting for click
Show Example Source Code
example.html
<bitty-1-1 data-connect="/modules/send-and-receive.js">
  <div data-receive="updateSendAndReceive">Waiting for click</div>
  <button data-send="updateSendAndReceive">Click Me</button>
</bitty-1-1>
<script src="/bitty-1.1.0-rc1.min.js" type="module"></script>
modules/send-and-receive.js
export default class {
  updateSendAndReceive(_event, element) {
    element.innerHTML = Date.now();
  }
}
ID: 0010-send-and-receive

Sending Multiple Signals

Waiting for Alfa
Waiting for Bravo
Waiting for Charlie
Show Example Source Code
example.html
<bitty-1-1 data-connect="/modules/send-multiple-signals.js">
  <div>
    <div data-receive="multiAlfa">Waiting for Alfa</div>
    <div data-receive="multiBravo">Waiting for Bravo</div>
    <div data-receive="multiCharlie">Waiting for Charlie</div>
  </div>
  <button data-send="multiAlfa|multiBravo|multiCharlie">Click Me</button>
</bitty-1-1>
<script src="/bitty-1.1.0-rc1.min.js" type="module"></script>
modules/send-multiple-signals.js
export default class {
  multiAlfa(_event, element) {
    element.innerHTML = Date.now();
  }

  multiBravo(_event, element) {
    element.innerHTML = Date.now();
  }

  multiCharlie(_event, element) {
    element.innerHTML = Date.now();
  }
}
ID: 0015-send-multiple-signals

Receiving Multiple Signals

Waiting for clicks
Show Example Source Code
example.html
<bitty-1-1 data-connect="/modules/receive-multiple-signals.js">
  <div data-receive="multiReceiveAlfa|multiReceiveBravo|multiReceiveCharlie">Waiting for clicks</div>
  <div>
    <button data-send="multiReceiveAlfa">Send Alfa</button>
    <button data-send="multiReceiveBravo">Send Bravo</button>
    <button data-send="multiReceiveCharlie">Send Charlie</button>
  </div>
</bitty-1-1>
<script src="/bitty-1.1.0-rc1.min.js" type="module"></script>
modules/receive-multiple-signals.js
export default class {
  multiReceiveAlfa(_event, element) {
    element.innerHTML = `Alfa`;
  }

  multiReceiveBravo(_event, element) {
    element.innerHTML = `Bravo`;
  }

  multiReceiveCharlie(_event, element) {
    element.innerHTML = `Charlie`;
  }
}
ID: 0017-recieve-multiple-signals

Using Additional Data Attributes

Waiting for clicks
Show Example Source Code
example.html
<bitty-1-1 data-connect="/modules/additional-attributes.js">
  <div data-receive="updateFromData">Waiting for clicks</div>
  <div>
    <button data-color="red" data-send="updateFromData">red</button>
    <button data-color="green" data-send="updateFromData">green</button>
    <button data-color="blue" data-send="updateFromData">blue</button>
  </div>
</bitty-1-1>
<script src="/bitty-1.1.0-rc1.min.js" type="module"></script>
modules/additional-attributes.js
export default class {
  updateFromData(event, element) {
    const selectedColor = event.target.dataset.color;
    ["red", "green", "blue"].forEach((color) => {
      if (color === selectedColor) {
        element.classList.add(color);
      } else {
        element.classList.remove(color);
      }
    });
    element.innerHTML = `Selected: ${selectedColor}`;
  }
}
ID: 0018-additional-attributes

Multiple Senders and Multiple Receivers

Waiting for click
Waiting for click
Waiting for click
Show Example Source Code
example.html
<bitty-1-1 data-connect="/modules/multiple-senders-and-multiple-receivers.js">
  <div>
    <div data-receive="bookTitle">Waiting for click</div>
    <div data-receive="bookAuthor">Waiting for click</div>
    <div data-receive="bookPages">Waiting for click</div>
  </div>
  <div>
    <button data-type="fiction" data-send="setBookType|bookTitle|bookAuthor|bookPages">Fiction</button>
    <button data-type="nonFiction" data-send="setBookType|bookTitle|bookAuthor|bookPages">Non-Fiction</button>
  </div>
</bitty-1-1>
<script src="/bitty-1.1.0-rc1.min.js" type="module"></script>
modules/multiple-senders-and-multiple-receivers.js
export default class {
  #books = {
    fiction: {
      title: "Neuromancer",
      author: "William Gibson",
      pages: 271,
    },
    nonFiction: {
      title: "On Writing",
      author: "Stephen King",
      pages: 288,
    },
  };
  #bookType = null;

  bookAuthor(_event, element) {
    element.innerHTML = `Author: ${this.#books[this.#bookType].author}`;
  }

  bookPages(_event, element) {
    element.innerHTML = `Pages: ${this.#books[this.#bookType].pages}`;
  }

  setBookType(event, _element) {
    this.#bookType = event.target.dataset.type;
  }

  bookTitle(_event, element) {
    element.innerHTML = `Title: ${this.#books[this.#bookType].title}`;
  }
}
ID: 0019-multiple-senders-and-multiple-receivers

Forward an Event Inside a Module

Waiting for click
Show Example Source Code
example.html
<bitty-1-1 data-connect="/modules/forward-inside-a-module.js">
  <div data-receive="forwardedSignal">Waiting for click</div>
  <button data-send="forwardUpdate">Click Me</button>
</bitty-1-1>
<script src="/bitty-1.1.0-rc1.min.js" type="module"></script>
modules/forward-inside-a-module.js
export default class {
  forwardedSignal(_event, element) {
    element.innerHTML = Date.now();
  }

  forwardUpdate(event, _element) {
    this.api.forward(event, "forwardedSignal");
  }
}
ID: 0020-forward-inside-a-module

Sending Directly from the bitty-1-1 Element

Show Example Source Code
example.html
<bitty-1-1 data-connect="/modules/send-from-bitty.js" data-send="updateFromBitty">
  <div data-receive="updateFromBitty"></div>
</bitty-1-1>
<script src="/bitty-1.1.0-rc1.min.js" type="module"></script>
modules/send-from-bitty.js
export default class {
  updateFromBitty(_event, element) {
    element.innerHTML = `Initialized at ${Date().toString()}`;
  }
}
ID: 0023-sending-from-bitty

Storing State

Waiting for click
Show Example Source Code
example.html
<bitty-1-1 data-connect="/modules/storing-state.js">
  <div data-receive="updateStoredState">Waiting for click</div>
  <button data-send="updateStoredState">Click Me</button>
</bitty-1-1>
<script src="/bitty-1.1.0-rc1.min.js" type="module"></script>
modules/storing-state.js
export default class {
  #currentState = "Off";

  updateStoredState(_event, element) {
    if (this.#currentState === "Off") {
      this.#currentState = "On";
    } else {
      this.#currentState = "Off";
    }
    element.innerHTML = this.#currentState;
  }
}
ID: 0025-storing-state

Calling Functions Without Receivers

Waiting for click
Show Example Source Code
example.html
<bitty-1-1 data-connect="/modules/calling-functions.js">
  <div>Waiting for click</div>
  <button data-send="updateWithoutReceiver">Click Me</button>
</bitty-1-1>
<script src="/bitty-1.1.0-rc1.min.js" type="module"></script>
modules/calling-functions.js
export default class {
  updateWithoutReceiver(_event, _element) {
    this.api.querySelector("div").innerHTML = Date.now();
  }
}
ID: 0030-calling-functions

Updating An Element Directly

Show Example Source Code
example.html
<bitty-1-1 data-connect="/modules/updating-self.js">
  <button data-send="updateSelf" data-receive="updateSelf">Click Me</button>
</bitty-1-1>
<script src="/bitty-1.1.0-rc1.min.js" type="module"></script>
modules/updating-self.js
export default class {
  updateSelf(_event, element) {
    element.innerHTML = Date.now();
  }
}
ID: 0040-updating-self

Using Event Data

Waiting on click
Show Example Source Code
example.html
<bitty-1-1 data-connect="/modules/using-event-data.js">
  <div data-receive="updateWithEventData">Waiting on click</div>
  <button data-send="updateWithEventData">Click Me</button>
</bitty-1-1>
<script src="/bitty-1.1.0-rc1.min.js" type="module"></script>
modules/using-event-data.js
export default class {
  updateWithEventData(event, element) {
    element.innerHTML = `${event.type} ${Date.now()}`;
  }
}
ID: 0043-using-event-data

Using Radio Buttons

Waiting
Show Example Source Code
example.html
<bitty-1-1 data-connect="/modules/using-radio-buttons.js">
  <div data-receive="updateFromRadioButtons">Waiting</div>
  <label>
    Alfa
    <input
      data-send="updateFromRadioButtons"
      value="Alfa"
      type="radio"
      name="radio-example"
    />
  </label>
  <label>
    Bravo
    <input
      data-send="updateFromRadioButtons"
      value="Bravo"
      type="radio"
      name="radio-example"
    />
  </label>
</bitty-1-1>
<script src="/bitty-1.1.0-rc1.min.js" type="module"></script>
modules/using-radio-buttons.js
export default class {
    updateFromRadioButtons(event, element) {
        element.innerHTML = `Selected: ${event.target.value}`;
    }
}
ID: 0044-using-radio-buttons

Using Input Text Elements

Waiting
Show Example Source Code
example.html
<bitty-1-1 data-connect="/modules/using-input-text-elements.js">
  <div data-receive="updateFromTextInput">Waiting</div>
  <input type="text" data-send="updateFromTextInput" />
</bitty-1-1>
<script src="/bitty-1.1.0-rc1.min.js" type="module"></script>
modules/using-input-text-elements.js
export default class {
  updateFromTextInput(event, element) {
    if (event.target.value !== "") {
      element.innerHTML = event.target.value;
    }
  }
}
ID: 0045-using-input-text-elements

Range Sliders

Waiting
Show Example Source Code
example.html
<bitty-1-1 data-connect="/modules/range-sliders.js">
  <div data-receive="updateFromRangeSlider">Waiting</div>
  <label>
    Send
    <input data-send="updateFromRangeSlider" type="range" />
  </label>
</bitty-1-1>
<script src="/bitty-1.1.0-rc1.min.js" type="module"></script>
modules/range-sliders.js
export default class {
  updateFromRangeSlider(event, element) {
    element.innerHTML = event.target.value;
  }
}
ID: 0050-range-sliders

Automatically Added UUIDs

Waiting for click
---
Show Example Source Code
example.html
<bitty-1-1 data-connect="/modules/element-uuids.js">
  <div data-receive="uuidDemo">Waiting for click <br />---</div>
  <div>
    <button data-send="uuidDemo">Alfa</button>
    <button data-send="uuidDemo">Bravo</button>
  </div>
</bitty-1-1>
<script src="/bitty-1.1.0-rc1.min.js" type="module"></script>
modules/element-uuids.js
export default class {
  uuidDemo(event, element) {
    element.innerHTML = `<div>From: ${event.target.dataset.uuid}</div>
        <div>To: ${element.dataset.uuid}</div>`;
  }
}
ID: 0060-element-uuids

Avoiding Text Input Feedback


Show Example Source Code
example.html
<bitty-1-1 data-connect="/modules/avoiding-text-input-feedback.js">
  <label>
    Alfa
    <input type="text" data-send="avoidInputFeedback" data-receive="avoidInputFeedback" />
  </label>
  <br>
  <label>
    Bravo
    <input type="text" data-send="avoidInputFeedback" data-receive="avoidInputFeedback" />
  </label>
</bitty-1-1>
<script src="/bitty-1.1.0-rc1.min.js" type="module"></script>
modules/avoiding-text-input-feedback.js
export default class {
  avoidInputFeedback(event, element) {
    if (element.dataset.uuid !== event.target.dataset.uuid) {
      element.value = event.target.value;
    }
  }
}
ID: 0070-avoiding-text-input-feedback.txt

Avoiding Range Slider Feedback


Show Example Source Code
example.html
<bitty-1-1 data-connect="/modules/avoiding-range-slider-feedback.js">
  <label>
    Alfa
    <input data-send="updateSliderFeedback" data-receive="updateSliderFeedback" type="range" />
  </label>
  <br />
  <label>
    Bravo
    <input data-send="updateSliderFeedback" data-receive="updateSliderFeedback" type="range" />
  </label>
</bitty-1-1>
<script src="/bitty-1.1.0-rc1.min.js" type="module"></script>
modules/avoiding-range-slider-feedback.js
export default class {
  updateSliderFeedback(event, element) {
    if (element.dataset.uuid !== event.target.dataset.uuid) {
      element.value = event.target.value;
    }
  }
}
ID: 0075-avoiding-range-slider-feedback

Initializing Values

Show Example Source Code
example.html
<bitty-1-1 data-connect="/modules/initialize-values.js">
  <label>
    Initialized to 90
    <input type="range" />
  </label>
</bitty-1-1>
<script src="/bitty-1.1.0-rc1.min.js" type="module"></script>
modules/initialize-values.js
export default class {
  bittyInit() {
    [...this.api.querySelectorAll("[type=range]")]
      .forEach((element) => {
        element.value = 90;
      });
  }
}
ID: 0100-initialize-values

Using Templates

Show Example Source Code
example.html
<bitty-1-1 data-connect="/modules/using-templates.js"></bitty-1-1>
<script src="/bitty-1.1.0-rc1.min.js" type="module"></script>
modules/using-templates.js
const template = document.createElement("template");
template.innerHTML =
  `<button data-send="updateFromTemplate" data-receive="updateFromTemplate">Click Me</button>`;

export default class {
  bittyInit() {
    this.api.replaceChildren(template.content.cloneNode(true));
  }

  updateFromTemplate(_event, element) {
    element.innerHTML = Date.now();
  }
}
ID: 0115-using-templates

Create Elements

Waiting for click
Show Example Source Code
example.html
<bitty-1-1 data-connect="/modules/create-elements.js">
  <div data-receive="createElements">
    Waiting for click
  </div>
  <div data-receive="elementsAdded">
    <button data-send="createElements|elementsAdded">
        Create Elements
    </button>
  </div>
</bitty-1-1>
<script src="/bitty-1.1.0-rc1.min.js" type="module"></script>
modules/create-elements.js
export default class {
  createElements(_event, element) {
    const display = document.createElement("div");
    display.innerHTML = "Waiting for slider";
    display.dataset.receive = "update";
    element.replaceChildren(display);
    const slider = document.createElement("input");
    slider.type = "range";
    slider.value = "0";
    slider.dataset.send = "update";
    element.appendChild(slider);
  }

  elementsAdded(_event, element) {
    element.innerHTML = "Elements added";
  }

  update(event, element) {
    element.innerHTML = event.target.value;
  }
}
ID: 0120-create-elements

Copy Button

The quick brown fox
jumps over
the lazy dog
Show Example Source Code
example.html
<bitty-1-1 data-connect="/modules/copy-button.js">
  <pre id="text-to-copy">
The quick brown fox
jumps over
the lazy dog</pre
  >
  <div>
    <button data-target="#text-to-copy" data-send="copyText">Copy Text</button>
  </div>
</bitty-1-1>
<script src="/bitty-1.1.0-rc1.min.js" type="module"></script>
modules/copy-button.js
export default class {
  #theTimeout = null;
  #originalText = "Copy";

  async copyText(event, _element) {
    const elToCopy = document.querySelector(event.target.dataset.target);
    if (event.target.innerHTML !== "Copied") {
      this.#originalText = event.target.innerHTML;
    }
    try {
      let content;
      if (elToCopy.value) {
        content = elToCopy.value;
      } else {
        content = elToCopy.innerText;
      }
      await navigator.clipboard.writeText(content);
      event.target.innerHTML = "Copied";
    } catch (err) {
      event.target.innerHTML = "Error copying";
    }
    if (this.#theTimeout !== null) {
      clearTimeout(this.#theTimeout);
    }
    this.#theTimeout = setTimeout(
      (theButton) => {
        event.target.innerHTML = this.#originalText;
      },
      2000,
      event.target,
    );
  }
}
ID: 0130-copy-button

Customize Event Listeners

Waiting for mouse
Show Example Source Code
example.html
<bitty-1-1 data-connect="/modules/alternate-event-listeners.js"
  data-listeners="mouseover|mouseout">
  <button data-send="sawMouse">
    Mouseover
  </button>
  <div data-receive="sawMouse">
    Waiting for mouse
  </div>
</bitty-1-1>
<script src="/bitty-1.1.0-rc1.min.js" type="module"></script>
modules/alternate-event-listeners.js
export default class {
  sawMouse(event, element) {
    element.innerHTML = `${event.type} at ${Date.now()}`;
  }
}
ID: 0190-alternate-event-listeners
Multiple Instances

Instance Isolation

Waiting
Waiting
Show Example Source Code
<bitty-1-1 data-connect="/modules/instance-isolation.js">
  <button data-send="updateIsolatedInstance">Click Me</button>
  <div data-receive="updateIsolatedInstance">Waiting</div>
</bitty-1-1>

<bitty-1-1 data-connect="/modules/instance-isolation.js">
  <button data-send="updateIsolatedInstance">Click Me</button>
  <div data-receive="updateIsolatedInstance">Waiting</div>
</bitty-1-1>
<script src="/bitty-1.1.0-rc1.min.js" type="module"></script>
export default class {
  #value = 0;

  updateIsolatedInstance(event, element) {
    // The same signal name is used in both
    // elements in this example. Separating
    // the data can be done by comparing
    // the bitty-1-1 component they are
    // connect to with the data from
    // the triggering event.

    // get the uuid of the parent bitty-1-1
    // component
    const bittyUUID = this.api.dataset.uuid;

    // get the uuid of the parent element from
    // the event target
    const checkUUID = event.target.parentNode.dataset.uuid;

    if (bittyUUID === checkUUID) {
      this.#value += 1;
      element.innerHTML = this.#value;
    }
  }
}

Sending Signals From Parents To Children

Waiting
Show Example Source Code
<bitty-1-1 data-connect="/modules/sending-signals-from-parents-to-children.js">  
  <div>
    <button data-send="demoParentToChildSignal">
      Click Me
    </button>
  </div>

  <div>
    <bitty-1-1 
      data-connect="/modules/sending-signals-from-parents-to-children.js">
      <div  data-receive="demoParentToChildSignal">
        Waiting
      </div>
    </bitty-1-1>
  </div>
</bitty-1-1>
<script src="/bitty-1.1.0-rc1.min.js" type="module"></script>
export default class {
  demoParentToChildSignal(event, element) {
    element.innerHTML = Date.now();
  }
}

Sending Signals from Children to Parents

Waiting
Show Example Source Code
<bitty-1-1 data-connect="/modules/sending-signals-up--parent.js">
    <div data-receive="demoSendingFromChildToParent">Waiting</div>
    <bitty-1-1 data-connect="/modules/sending-signals-up--child.js">  
      <button data-send="demoSendingFromChildToParent">Click Me</button>
    </bitty-1-1>
</bitty-1-1>
<script src="/bitty-1.1.0-rc1.min.js" type="module"></script>
export default class {
  demoSendingFromChildToParent(_event, element) {
    element.innerHTML = Date.now();
  }
}

Sending Signals Across The DOM

Show Example Source Code
<bitty-1-1 data-connect="/modules/sending-across-the-dom.js">
  <button data-send="coverageDemo" data-receive="coverageDemo">Waiting</button>
  <button data-send="coverageDemo" data-receive="coverageDemo">Waiting</button>
  <button data-send="coverageDemo" data-receive="coverageDemo">Waiting</button>
  <ul>
    <li>
      <bitty-1-1 data-connect="/modules/sending-across-the-dom.js">
        <button data-send="coverageDemo" data-receive="coverageDemo">Waiting</button>
        <button data-send="coverageDemo" data-receive="coverageDemo">Waiting</button>
        <button data-send="coverageDemo" data-receive="coverageDemo">Waiting</button>
      </bitty-1-1>
      <ul>
        <li>
        <bitty-1-1 data-connect="/modules/sending-across-the-dom.js">
          <button data-send="coverageDemo" data-receive="coverageDemo">Waiting</button>
          <button data-send="coverageDemo" data-receive="coverageDemo">Waiting</button>
          <button data-send="coverageDemo" data-receive="coverageDemo">Waiting</button>
        </bitty-1-1>
          <ul>
            <li>
            <bitty-1-1 data-connect="/modules/sending-across-the-dom.js">
              <button data-send="coverageDemo" data-receive="coverageDemo">Waiting</button>
              <button data-send="coverageDemo" data-receive="coverageDemo">Waiting</button>
              <button data-send="coverageDemo" data-receive="coverageDemo">Waiting</button>
            </bitty-1-1>
            </li>
          </ul>
        </li>
      </ul>
    </li>
  </ul>

  <button data-send="coverageDemo" data-receive="coverageDemo">Waiting</button>
  <button data-send="coverageDemo" data-receive="coverageDemo">Waiting</button>
  <button data-send="coverageDemo" data-receive="coverageDemo">Waiting</button>
  <ul>
    <li>
      <bitty-1-1 data-connect="/modules/sending-across-the-dom.js">
        <button data-send="coverageDemo" data-receive="coverageDemo">Waiting</button>
        <button data-send="coverageDemo" data-receive="coverageDemo">Waiting</button>
        <button data-send="coverageDemo" data-receive="coverageDemo">Waiting</button>
      </bitty-1-1>
      <ul>
        <li>
        <bitty-1-1 data-connect="/modules/sending-across-the-dom.js">
          <button data-send="coverageDemo" data-receive="coverageDemo">Waiting</button>
          <button data-send="coverageDemo" data-receive="coverageDemo">Waiting</button>
          <button data-send="coverageDemo" data-receive="coverageDemo">Waiting</button>
        </bitty-1-1>
          <ul>
            <li>
            <bitty-1-1 data-connect="/modules/sending-across-the-dom.js">
              <button data-send="coverageDemo" data-receive="coverageDemo">Waiting</button>
              <button data-send="coverageDemo" data-receive="coverageDemo">Waiting</button>
              <button data-send="coverageDemo" data-receive="coverageDemo">Waiting</button>
            </bitty-1-1>
            </li>
          </ul>
        </li>
      </ul>
    </li>
  </ul>
</bitty-1-1>
<script src="/bitty-1.1.0-rc1.min.js" type="module"></script>
export default class {
  coverageDemo(event, element) {
    if (element.dataset.uuid === event.target.dataset.uuid) {
      element.innerHTML = "HERE";
    } else {
      element.innerHTML = "----";
    }
  }
}

Storing Data In Parent

-
Show Example Source Code
<bitty-1-1 data-connect="/modules/storing-data-in-parent.js|Parent">

  <div data-receive="incrementDemo|decrementDemo">-</div>

  <bitty-1-1 data-connect="/modules/storing-data-in-parent.js|Child">
    <button data-send="incrementDemo">Increment</button>
  </bitty-1-1>

  <bitty-1-1 data-connect="/modules/storing-data-in-parent.js|Child">
    <button data-send="decrementDemo">Decrement</button>
  </bitty-1-1>
</bitty-1-1>
<script src="/bitty-1.1.0-rc1.min.js" type="module"></script>
export class Parent {
  #value = 0;
  decrementDemo(_event, element) {
    this.#value -= 1;
    element.innerHTML = this.#value;
  }
  incrementDemo(_event, element) {
    this.#value += 1;
    element.innerHTML = this.#value;
  }
}

export class Child {
  // no methods required
}

Share Global Data Between Siblings

Show Example Source Code
<bitty-1-1 data-connect="/modules/sharing-global-data.js">
  <button data-send="globalDataExample" data-receive="globalDataExample">Click Me</button>
</bitty-1-1>

<bitty-1-1 data-connect="/modules/sharing-global-data.js">
  <button data-send="globalDataExample" data-receive="globalDataExample">Click Me</button>
</bitty-1-1>
<script src="/bitty-1.1.0-rc1.min.js" type="module"></script>
const state = {
  value: 0,
};

export default class {
  globalDataExample(event, element) {
    if (element.dataset.uuid === event.target.dataset.uuid) {
      state.value += 1;
      element.innerHTML = `Latest value seen: ${state.value}`;
    }
  }
}
Loading Functionality from the Page
Waiting for click

bitty-1-1 can use <script> tags on the page for functinoality. For example, this <script> is in the <head> element of this page:

<script>
window.bittyClasses = {
  InlineExample: class { 
    updateFromPage(_event, el) {
      el.innerHTML = "PASSED";
      el.classList.add("test-passed");
    }
  }
};
</script>

Using it is done by setting the data-connect attribute of a bitty-1-1 to the name of the class in the bittyClasses object:

<bitty-1-1 data-connect="InlineExample">
  <div data-receive="updateFromPage">Waiting for click</div>
  <button data-send="updateFromPage">Click Me</button>
</bitty-1-1>

TODO

Show using window.BittyClass as default for a single class call that lets you use <bitty-1-1> without a data-connect attribute

<script>
window.BittyClass = class {
  updateFromPageDefaultClass(_event, el) {
    el.innerHTML = "PASSED";
    el.classList.add("test-passed");
  }
}
</script>
Documentation In Progress

Docs are in the process of being overhauled. Check out the code from the examples and test cases for the time being.

Release Notes

Version: 1.1.0-rc1

Oct. 4, 2025

Version: 1.0.0

Oct. 4, 2025

Version: 1.0.0-rc5

Oct. 4, 2025

Version: 1.0.0-rc4

Oct. 1, 2025

Version: 1.0.0-rc3

Sept. 23, 2025

Version: 1.0.0-rc2

Sept. 19, 2025

Version: 1.0.0-rc1

Sept. 18, 2025

Initial release candidate for version 1.0.0.

No changes since v0.4.0.

Version: 0.4.0

Sept. 17, 2025

Version: 0.3.0

Sept. 17, 2025

Big refactor based on experience using 0.2.0.

Version: 0.2.3

June 5, 2025

Lots of error handling work in this one.

Version: 0.2.2

June 4, 2025

Added UUIDs for pending error handling. Shuffeld a bunch of stuff around to make the examples look nicer.

Version: 0.2.1

June 3, 2025

Some more wiring and some support tools for making the demo/docs site.

Version: 0.2.0

June 3, 2025

Setting up a bunch of the basic wiring.

Version: 0.1.0

June 2, 2025

Getting the project started.

Test Suite

Test Results

bittyInit is called automatically
FAILED
Test Code
ID: 0005-bitty-init-is-called
<bitty-1-1 data-connect="/tests/[@ folder.name @]/test.js">
  <div class="test">FAILED</div>
</bitty-1-1>
function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

export default class {
  async bittyInit() {
    await sleep(100) // time pad for test
    this.api.querySelector("div").innerHTML = "PASSED";
  }
}
Basic Send and Receive
FAILED
Test Code
ID: 0010-basic-send-receive
<bitty-1-1 data-connect="/tests/[@ folder.name @]/test.js">
  <button data-send="runTest0010">Test Trigger</button>
  <div class="test" data-receive="runTest0010">FAILED</div>
</bitty-1-1>
function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

export default class {
  async bittyInit() {
    await sleep(100) // time pad for test
    this.api.querySelector("button").click();
  }

  runTest0010(_event, el) {
    el.innerHTML = "PASSED";
  }
}
Nest Element Sending and Receiveing
---
  • FAILED
Test Code
ID: 0015-nestined-send-and-receive
<bitty-1-1 data-connect="/tests/[@ folder.name @]/test.js">
  <ul>
    <li><button data-send="runTest0015">Test Trigger</button></li>
  </ul>
  <div>---</div>
  <ul>
    <li><div class="test" data-receive="runTest0015">FAILED</div></li>
  </ul>
</bitty-1-1>
function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

export default class {
  async bittyInit() {
    await sleep(100) // time pad for test
    this.api.querySelector("button").click();
  }

  runTest0015(_event, el) {
    el.innerHTML = "PASSED";
  }
}
Send from the bitty-1-1 element
FAILED
Test Code
ID: 0020-send-from-bitty-js
<bitty-1-1 data-connect="/tests/[@ folder.name @]/test.js" data-send="runTest0020">
  <div class="test" data-receive="runTest0020">FAILED</div>
</bitty-1-1>
export default class {
  runTest0020(_event, el) {
    el.innerHTML = "PASSED";
  }
}
Multiple sends from a single element
FAILED
FAILED
FAILED
Test Code
ID: 0030-send-multiple-signals
<bitty-1-1 data-connect="/tests/[@ folder.name @]/test.js">
  <button data-send="runTestAlfa0030|runTestBravo0030|runTestCharlie0030">Test Trigger</button>
  <div class="test" data-receive="runTestAlfa0030">FAILED</div>
  <div class="test" data-receive="runTestBravo0030">FAILED</div>
  <div class="test" data-receive="runTestCharlie0030">FAILED</div>
</bitty-1-1>
function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

export default class {
  async bittyInit() {
    await sleep(100) // time pad for test
    this.api.querySelector("button").click();
  }
  runTestAlfa0030(_event, el) {
    el.innerHTML = "PASSED";
  }
  runTestBravo0030(_event, el) {
    el.innerHTML = "PASSED";
  }
  runTestCharlie0030(_event, el) {
    el.innerHTML = "PASSED";
  }
}
Multiple Receivers for a Single Sender
FAILED
FAILED
FAILED
Test Code
ID: 0040-multiple-receivers
<bitty-1-1 data-connect="/tests/[@ folder.name @]/test.js">
  <button data-send="runTest0040">Test Trigger</button>
  <div class="test" data-receive="runTest0040">FAILED</div>
  <div class="test" data-receive="runTest0040">FAILED</div>
  <div class="test" data-receive="runTest0040">FAILED</div>
</bitty-1-1>
function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

export default class {
  async bittyInit() {
    await sleep(100) // time pad for test
    this.api.querySelector("button").click();
  }
  runTest0040(_event, el) {
    el.innerHTML = "PASSED";
  }
}
Access data-* Attributes from Sending Elements
FAILED
Test Code
ID: 0050-accessing-data-from-sending-element
<bitty-1-1 data-connect="/tests/[@ folder.name @]/test.js">
  <button data-status="PASSED" data-send="runTest50">Test Trigger</button>
  <div class="test" data-receive="runTest50">FAILED</div>
</bitty-1-1>
function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

export default class {
  async bittyInit() {
    await sleep(100) // time pad for test
    this.api.querySelector("button").click();
  }

  runTest50(event, element) {
    element.innerHTML = event.target.dataset.status;
  }
}
Access data-* Attributes from Receiving Elements
FAILED
Test Code
ID: 0060-access-data-from-receiving-element
<bitty-1-1 data-connect="/tests/[@ folder.name @]/test.js">
  <button data-send="runTest0060">Test Trigger</button>
  <div class="test" data-status="PASSED" data-receive="runTest0060">FAILED</div>
</bitty-1-1>
function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

export default class {
  async bittyInit() {
    await sleep(100) // time pad for test
    this.api.querySelector("button").click();
  }
  runTest0060(_event, el) {
    el.innerHTML = el.dataset.status;
  }
}
Sending Many Signals to Many Receivers
FAILED
FAILED
FAILED
Test Code
ID: 0070-many-sends-to-many-receivers
<bitty-1-1 data-connect="/tests/[@ folder.name @]/test.js">
  <button data-send="runTestAlfa0070|runTestBravo0070|runTestCharlie0070">Test Trigger</button>
  <div class="test" data-receive="runTestAlfa0070">FAILED</div>
  <div class="test" data-receive="runTestBravo0070">FAILED</div>
  <div class="test" data-receive="runTestCharlie0070">FAILED</div>
</bitty-1-1>
function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

export default class {
  async bittyInit() {
    await sleep(100) // time pad for test
    this.api.querySelector("button").click();
  }
  runTestAlfa0070(_event, el) {
    el.innerHTML = "PASSED";
  }
  runTestBravo0070(_event, el) {
    el.innerHTML = "PASSED";
  }
  runTestCharlie0070(_event, el) {
    el.innerHTML = "PASSED";
  }
}
Forward an Event Inside a Module
FAILED
Test Code
ID: 0075-forward-inside-module
<bitty-1-1 data-connect="/tests/[@ folder.name @]/test.js">
  <button data-send="runTest0075">Test Trigger</button>
  <div class="test" data-receive="forwardEvent0075">FAILED</div>
</bitty-1-1>
function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

export default class {
  async bittyInit() {
    await sleep(100) // time pad for test
    this.api.querySelector("button").click();
  }

  runTest0075(event, _el) {
    this.api.forward(event, "forwardEvent0075");
  }

  forwardEvent0075(_event, el) {
    el.innerHTML = "PASSED";
  }
}
Storing State
FAILED
Test Code
ID: 0080-storing-state
<bitty-1-1 data-connect="/tests/[@ folder.name @]/test.js">
  <button data-send="runTest0080">Test Trigger</button>
  <div class="test" data-receive="runTest0080">FAILED</div>
</bitty-1-1>
function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

export default class {
  #count = 0;
  async bittyInit() {
    await sleep(100) // time pad for test
    this.api.querySelector("button").click();
    this.api.querySelector("button").click();
    this.api.querySelector("button").click();
  }

  runTest0080(_event, el) {
    this.#count += 1;
    if (this.#count === 3) {
      el.innerHTML = "PASSED";
    }
  }
}
Sending and Receiving from the Same Element
Test Code
ID: 0090-updating-self-loopback-signal
<bitty-1-1 data-connect="/tests/[@ folder.name @]/test.js">
  <button class="test" data-send="runTest0090" data-receive="runTest0090">Test Trigger</button>
</bitty-1-1>
function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

export default class {
  async bittyInit() {
    await sleep(100); // time pad for test
    const button = this.api.querySelector("button");
    button.click();
  }
  runTest0090(_event, el) {
    el.innerHTML = "PASSED";
  }
}
Get Event Type
FAILED
Test Code
ID: 0100-get-event-type
<bitty-1-1 data-connect="/tests/[@ folder.name @]/test.js">
  <button data-send="runTest0100">Test Trigger</button>
  <div class="test" data-receive="runTest0100">FAILED</div>
</bitty-1-1>
function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

export default class {
  async bittyInit() {
    await sleep(100) // time pad for test
    this.api.querySelector("button").click();
  }
  runTest0100(event, el) {
    if (event.type === "click") {
      el.innerHTML = "PASSED";
    }
  }
}
Verify UUIDs are Created on Sending Elements
FAILED
Test Code
ID: 0110-verify-uuids-exist-on-senders
<bitty-1-1 data-connect="/tests/[@ folder.name @]/test.js">
  <button data-send="runTest0110">Test Trigger</button>
  <div class="test" data-receive="runTest0110">FAILED</div>
</bitty-1-1>
function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

export default class {
  async bittyInit() {
    await sleep(100) // time pad for test
    this.api.querySelector("button").click();
  }

  runTest0110(event, el) {
    if (event.target.dataset.uuid !== undefined) {
      el.innerHTML = "PASSED";
    }
  }
}
Verify UUIDs are Created on Receiving Elements
FAILED
Test Code
ID: 0120-verify-uuids-exist-on-receivers
<bitty-1-1 data-connect="/tests/[@ folder.name @]/test.js">
  <button data-send="runTest0120">Test Trigger</button>
  <div class="test" data-receive="runTest0120">FAILED</div>
</bitty-1-1>
function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

export default class {
  async bittyInit() {
    await sleep(100) // time pad for test
    this.api.querySelector("button").click();
  }

  runTest0120(_event, element) {
    if (element.dataset.uuid !== undefined) {
      element.innerHTML = "PASSED";
    }
  }
}
Verify UUIDs Exist On All Elements
FAILED
Test Code
ID: 0125-uuids-exist-on-all-elements
<bitty-1-1 data-connect="/tests/[@ folder.name @]/test.js">
  <div class="test">FAILED</div>
</bitty-1-1>
function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

export default class {
  async bittyInit() {
    await sleep(100) // time pad for test
    const el = this.api.querySelector("div");
    if (el.dataset.uuid) {
      el.innerHTML = "PASSED";
    }
  }
}
Verify UUIDs Are Added To Events
FAILED
Test Code
ID: 0127-uuids-exist-on-events
<bitty-1-1 data-connect="/tests/[@ folder.name @]/test.js">
  <button data-send="runTest0127">Test Trigger</button>
  <div class="test" data-receive="runTest0127">FAILED</div>
</bitty-1-1>
function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

export default class {
  async bittyInit() {
    await sleep(100) // time pad for test
    this.api.querySelector("button").click();
  }

  runTest0127(event, element) {
    if (event.uuid !== undefined) {
      element.innerHTML = "PASSED";
    }
  }
}
Existing data-uuid Attributes Aren't Overwritten
FAILED
FAILED
Test Code
ID: 0128-uuids-are-not-overwritten
<bitty-1-1 data-connect="/tests/[@ folder.name @]/test.js">
  <div class="test" data-uuid="original-uuid">FAILED</div>
  <div class="test" data-receive="testStub" data-uuid="original-uuid">FAILED</div>
</bitty-1-1>
function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

export default class {
  async bittyInit() {
    await sleep(100) // time pad for test
    const els = this.api.querySelectorAll("[data-uuid]");
    [...els].forEach((el) => {
      if (el.dataset.uuid === "original-uuid") {
        el.innerHTML = "PASSED";
      }
    });
  }
}
Ensure New Elements Get a data-uuid if They Have data-send/receive
FAILED
Test Code
ID: 0130-create-an-element
<bitty-1-1 data-connect="/tests/[@ folder.name @]/test.js">
  <button data-send="runTest0130">Test Trigger</button>
  <div class="test-element-wrapper" data-receive="runTest0130">FAILED</div>
</bitty-1-1>
function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

export default class {
  async bittyInit() {
    await sleep(100); // time pad for test
    this.api.querySelector("button").click();
  }

  async runTest0130(_event, element) {
    const newDiv = document.createElement("div");
    const newButton = document.createElement("button");
    newButton.classList.add("test");
    newButton.dataset.receive = "placeholderToGenerateUUID";
    newButton.innerHTML = "FAILED";
    newDiv.appendChild(newButton);
    element.replaceChildren(newDiv);
    // sleep for test to wait for observer
    // to update the UUID.
    await sleep(100);
    if (newButton.dataset.uuid !== undefined) {
      newButton.innerHTML = "PASSED";
    }
  }
}
Ensure Elements Made from Templates Get UUIDs
FAILED
Test Code
ID: 0140-ensure-template-elements-get-uuids
<bitty-1-1 data-connect="/tests/[@ folder.name @]/test.js">
  <button data-send="runTest0140">Test Trigger</button>
  <div class="test-element-wrapper" data-receive="runTest0140">FAILED</div>
</bitty-1-1>
function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

const template = document.createElement("template");
template.innerHTML =
  `<div><div><button class="test" data-send="testStub">FAILED</button></div></div>`;

export default class {
  async bittyInit() {
    await sleep(100); // time pad for test
    this.api.querySelector("button").click();
  }

  async runTest0140(_event, element) {
    let newButton = template.content.cloneNode(true);
    element.replaceChildren(newButton);
    element.childNodes[0].classList.add("test");
    // sleep for test to wait for observer
    // to update the UUID.
    await sleep(100);
    if (element.childNodes[0].dataset.uuid !== undefined) {
      element.childNodes[0].innerHTML = "PASSED";
    }
  }
}
Verify the bittyInit() Function Explicitly
FAILED
Test Code
ID: 0160-init-function-works
<bitty-1-1 data-connect="/tests/[@ folder.name @]/test.js" class="test">FAILED</bitty-1-1>
function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

export default class {
  async bittyInit() {
    await sleep(100) // time pad for test
    this.api.innerHTML = "PASSED";
  }
}
Use data-send To Call a Function When There's No Element With a Corresponding Receiver
FAILED
Test Code
ID: 0170-use-data-send-without-a-receiver
<bitty-1-1 data-connect="/tests/[@ folder.name @]/test.js">
  <button data-send="runTest0170">Test Trigger</button>
  <div class="test">FAILED</div>
</bitty-1-1>
function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

export default class {
  async bittyInit() {
    await sleep(100) // time pad for test
    this.api.querySelector("button").click();
  }

  runTest0170(event, _el) {
    this.api.querySelector("div").innerHTML = "PASSED";
  }
}
Chain this.api.forward() calls
FAILED
FAILED
FAILED
FAILED
Test Code
ID: 0220-chain-forword-api-calls
<bitty-1-1 data-connect="/tests/[@ folder.name @]/test.js">
    <button data-send="runTest0220">Test Trigger</button>
    <div class="test" data-receive="runTest0220">FAILED</div>
    <div class="test" data-receive="secondSignal0220">FAILED</div>
    <div class="test" data-receive="thirdSignal0220">FAILED</div>
    <div class="test" data-receive="fourthSignal0220">FAILED</div>
</bitty-1-1>
// Ensure the `data-send` value of the
// event generating element doesn't
// get changed
function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}


export default class {
  #counterAlfa = 0;
  #counterBravo = 0;
  #counterCharlie = 0;
  #counterDelta = 0;

  async bittyInit() {
    await sleep(100) // time pad for test
    const button = this.api.querySelector("button");
    button.click();
    button.click();
    button.click();
    button.click();
  }

  runTest0220(event, element) {
    this.#counterAlfa += 1;
    event.target.dataset.counter = `${this.#counterAlfa}`;
    if (event.target.dataset.counter == "4") {
      element.innerHTML = "PASSED";
    }
    this.api.forward(event, "secondSignal0220");
  }

  secondSignal0220(event, element) {
    this.#counterBravo += 1;
    event.target.dataset.counter = `${this.#counterBravo}`;
    if (event.target.dataset.counter == "4") {
      element.innerHTML = "PASSED";
    }
    this.api.forward(event, "thirdSignal0220");
  }

  thirdSignal0220(event, element) {
    this.#counterCharlie += 1;
    event.target.dataset.counter = `${this.#counterCharlie}`;
    if (event.target.dataset.counter == "4") {
      element.innerHTML = "PASSED";
    }
    this.api.forward(event, "fourthSignal0220");
  }

  fourthSignal0220(event, element) {
    this.#counterDelta += 1;
    event.target.dataset.counter = `${this.#counterDelta}`;
    if (event.target.dataset.counter == "4") {
      element.innerHTML = "PASSED";
    }
  }

  //
}
Forward Multiple Signals
FAILED
FAILED
FAILED
FAILED
Test Code
ID: 0230-forward-multiple-signals
<bitty-1-1 data-connect="/tests/[@ folder.name @]/test.js">
    <button data-send="runTest0230">Test Trigger</button>
    <div class="test" data-receive="runTest0230">FAILED</div>
    <div class="test" data-receive="secondSignal0230">FAILED</div>
    <div class="test" data-receive="thirdSignal0230">FAILED</div>
    <div class="test" data-receive="fourthSignal0230">FAILED</div>
</bitty-1-1>
function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

export default class {
  async bittyInit() {
    await sleep(100); // time pad for test
    const button = this.api.querySelector("button");
    button.click();
  }

  runTest0230(event, element) {
    element.innerHTML = "PASSED";
    this.api.forward(
      event,
      "secondSignal0230|thirdSignal0230|fourthSignal0230",
    );
  }

  secondSignal0230(_event, element) {
    element.innerHTML = "PASSED";
  }

  thirdSignal0230(_event, element) {
    element.innerHTML = "PASSED";
  }

  fourthSignal0230(_event, element) {
    element.innerHTML = "PASSED";
  }
}
Call bittyInit() with await if it's async
FAILED
Test Code
ID: 0250-async-bitty-init
<bitty-1-1 data-connect="/tests/[@ folder.name @]/test.js">
  <div class="test">FAILED</div>
</bitty-1-1>
function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

export default class {
  async bittyInit() {
    await sleep(100);
    const el = this.api.querySelector("div");
    el.innerHTML = "PASSED";
  }
}
Use this.api.querySelector()
FAILED
Test Code
ID: 0260-use-api-query-selector
<bitty-1-1 data-connect="/tests/[@ folder.name @]/test.js">
  <div id="testApiQuerySelectorTarget" class="test">FAILED</div>
</bitty-1-1>
export default class {
  bittyInit() {
    const el = this.api.querySelector("#testApiQuerySelectorTarget");
    el.innerHTML = "PASSED";
  }
}
Documnet query selector
FAILED
Test Code
ID: 0270-use-document-query-selector
<div id="testDocumentQuerySelectorTarget" class="test">FAILED</div>

<bitty-1-1 data-connect="/tests/[@ folder.name @]/test.js">
    <button data-send="runTest0270">Test Trigger</button>
</bitty-1-1>
export default class {
  bittyInit() {
    this.api.querySelector("button").click();
  }

  runTest0270(_event, _element) {
    const el = document.querySelector("#testDocumentQuerySelectorTarget");
    el.innerHTML = "PASSED";
  }
}
Forward a Signal Without an Event
FAILED
Test Code
ID: 0280-forward-without-event
<bitty-1-1 data-connect="/tests/[@ folder.name @]/test.js">
    <div class="test" data-receive="runTest0280">FAILED</div>
</bitty-1-1>
export default class {
  bittyInit() {
    this.api.forward(null, "runTest0280");
  }

  runTest0280(_event, element) {
    element.innerHTML = "PASSED";
  }
}
Check init Order
FAILED
Test Code
ID: 0290-check-init-order
<bitty-1-1 
  data-connect="/tests/[@ folder.name @]/test.js"
  data-send="runTest0290"
>
    <div class="test" data-receive="runTest0290">FAILED</div>
</bitty-1-1>
export default class {
  #textString = "FAILED";

  bittyInit() {
    this.#textString = "PASSED";
  }

  runTest0290(_event, el) {
    el.innerHTML = this.#textString;
  }
}
Load New Node Receivers
FAILED
Test Code
ID: 0300-load-new-nodes
<bitty-1-1 data-connect="/tests/[@ folder.name @]/test.js">
  <button data-send="runTest0300">Test Trigger</button>
  <div class="test" data-receive="runTest0300">FAILED</div>
</bitty-1-1>
function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

export default class {
  async bittyInit() {
    await sleep(100);
    const newTree = document.createElement("div");
    newTree.innerHTML = `<div>
    <div class="test" data-receive="runTest0300">FAILED</div>
    </div>`;
    this.api.appendChild(newTree);
    await sleep(100);
    this.api.querySelector("button").click();
  }

  runTest0300(_event, el) {
    el.innerHTML = "PASSED";
  }
}
Load Default window.BittyClass from Page (Manual Test)
waiting
Test Code
ID: 0330-load-default-page-class
<bitty-1-1>
  <div data-receive="updateFromPageDefaultClass">waiting</div>
  <button data-send="updateFromPageDefaultClass">Test Trigger</button>
</bitty-1-1>
// This test comes from `window.BittyClass`
// on the parent HTML page.
Load Specific Class From window.BittyClasses (Manual Test)
waiting
Test Code
ID: 0340-load-directly-from-page
<bitty-1-1 data-connect="InlineExample">
  <div data-receive="updateFromPage">waiting</div>
  <button data-send="updateFromPage">Test Trigger</button>
</bitty-1-1>
// This test comes from `window.BittyClasses`
// on the parent HTML page.
Change Event Listeners
Manual Test By Mousing Over
Test Code
ID: 0350-change-event-listeners
<bitty-1-1 
  data-connect="/tests/[@ folder.name @]/test.js"
  data-listeners="mouseover|mouseout"
>
  <button data-send="runTest0350">Test Target For Mouseover</button>
  <div data-receive="runTest0350">Manual Test By Mousing Over</div>
</bitty-1-1>
export default class {
  runTest0350(_event, element) {
    element.innerHTML = "PASSED";
    element.classList.add("test-passed");
  }
}
Nested bitty data-send does not bubble
PASSED
Test Code
ID: 0360-nested-send-does-not-bubble
<bitty-1-1 
    data-connect="/tests/[@ folder.name @]/test.js|Parent">
  <div class="test" data-receive="runTest0360">PASSED</div>
  <bitty-1-1 
      data-connect="/tests/[@ folder.name @]/test.js|Child"
      data-send="runTest0360"
  >
  </bitty-1-1>
</bitty-1-1>
export class Parent {
  runTest0360(_event, el) {
    el.innerHTML = "FAILED";
  }
}

export class Child {
  runTest0360(_event, el) {
    if (el) {
      el.innerHTML = "FAILED";
    }
  }
}
bitty element data-send uses bittysend event
FAILED
Test Code
ID: 0370-bittysend-event
<bitty-1-1 
  data-connect="/tests/[@ folder.name @]/test.js"
  data-send="runTest0370"
>
  <div class="test" data-receive="runTest0370">FAILED</div>
</bitty-1-1>
export default class {
  runTest0370(event, el) {
    if (event.type === "bittytagdatasend") {
      el.innerHTML = "PASSED";
    }
  }
}
Forward bitty tag data-send event
FAILED
Test Code
ID: 0380-forwart-bitty-tag-send
<bitty-1-1 
  data-connect="/tests/[@ folder.name @]/test.js"
  data-send="runTest0380"
>
  <div class="test" data-receive="runTest0380forward">FAILED</div>
</bitty-1-1>
export default class {
  runTest0380(event, _el) {
    this.api.forward(event, "runTest0380forward");
  }

  runTest0380forward(event, el) {
    if (event.type = "bittytagdatasend") {
      el.innerHTML = "PASSED";
    }
  }
}
License

MIT License

Copyright (c) 2025 Alan Smith - https://bitty.alanwsmith.com/

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice, this permission notice, and the ID "2y1pBoEREr3eWA1ubCCOXdmRCdn" shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Feedback Requested

bitty is currently Version: 1.1.0-rc1. Play around with it. Let me know if you find bugs or show-stoppers.

Happy Coding

A lot of work into making bitty as simple as possible. I hope that simplicity helps you enjoy making things for the web.

- alan