bitty
Overview
bitty is a web component. It uses signals to make pages reactive. For example:
The bitty API is made from data-* attributes. For example, here's the HTML that makes up the example:
Show Timestamp Waiting for click
- The bitty-1-1 tag's data-connect attribute defines the path to a JavaScript module responsible for providing functionality.
- The button tag's data-send attribute sets it up to send update signals when its clicked.
- The div tag's data-receive attribute registers it to react to update signals when they occur.
Functionality
The update values from the data-send and data-receive attributes map to a function in the module with the same name.
The arguments passed to the function are:
-
The event that triggered the update (e.g. click events on the button in the example)
-
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
Show Example Source Code
Waiting for click Click Me
Sending Multiple Signals
Show Example Source Code
Waiting for Alfa Waiting for Bravo Waiting for Charlie Click Me
Receiving Multiple Signals
Show Example Source Code
Waiting for clicks Send Alfa Send Bravo Send Charlie
Using Additional Data Attributes
Show Example Source Code
Waiting for clicks red green blue
Multiple Senders and Multiple Receivers
Show Example Source Code
Waiting for click Waiting for click Waiting for click Fiction Non-Fiction
,
nonFiction: ,
};
#bookType = null;
}
Forward an Event Inside a Module
Show Example Source Code
Waiting for click Click Me
Sending Directly from the bitty-1-1 Element
Show Example Source Code
Storing State
Show Example Source Code
Waiting for click Click Me
Calling Functions Without Receivers
Show Example Source Code
Waiting for click Click Me
Updating An Element Directly
Show Example Source Code
Click Me
Using Event Data
Show Example Source Code
Waiting on click Click Me
Using Radio Buttons
Show Example Source Code
Waiting Alfa Bravo
Using Input Text Elements
Show Example Source Code
Waiting
Range Sliders
Show Example Source Code
Waiting Send
Automatically Added UUIDs
---
Show Example Source Code
Waiting for click --- Alfa Bravo
Avoiding Text Input Feedback
Show Example Source Code
Alfa Bravo
Avoiding Range Slider Feedback
Show Example Source Code
Alfa Bravo
Initializing Values
Show Example Source Code
Initialized to 90
Using Templates
Show Example Source Code
const template = document.;
template. =
`<button data-send="updateFromTemplate" data-receive="updateFromTemplate">Click Me</button>`;
Create Elements
Show Example Source Code
Waiting for click Create Elements
Copy Button
The quick brown fox jumps over the lazy dog
Show Example Source Code
The quick brown fox jumps over the lazy dog Copy Text
Customize Event Listeners
Show Example Source Code
Mouseover Waiting for mouse
Multiple Instances
- Multiple bitty-1-1 instances can be used on a single page.
- Signals can be sent between instances without restriction.
- Each instance can maintain its own state in private member variables (e.g. #counter).
- Each instance can also access global data from the page
Instance Isolation
Show Example Source Code
Click Me
Waiting
Click Me
Waiting
Sending Signals From Parents To Children
Show Example Source Code
Click Me
Waiting
Sending Signals from Children to Parents
Show Example Source Code
Waiting
Click Me
Sending Signals Across The DOM
Show Example Source Code
Waiting
Waiting
Waiting
Waiting
Waiting
Waiting
Waiting
Waiting
Waiting
Waiting
Waiting
Waiting
Waiting
Waiting
Waiting
Waiting
Waiting
Waiting
Waiting
Waiting
Waiting
Waiting
Waiting
Waiting
Storing Data In Parent
Show Example Source Code
-
Increment
Decrement
Parent
Child
Share Global Data Between Siblings
Show Example Source Code
Click Me
Click Me
const state = ;
Loading Functionality from the Page
bitty-1-1 can use <script>
tags on
the page for functinoality. For example,
this <script>
is in the <head>
element
of this page:
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:
Waiting for click
Click Me
TODO
Show using window.BittyClass
as default for
a single class call that lets you use
<bitty-1-1>
without a
data-connect
attribute
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
-
<bitty-1-1>
can be called without adata-connect
attribute. When it is, it looks for awindow.BittyClass
on the page and uses it if it's available. -
Removed .error() method in favor of calling
console.error()
directly in order to get useful line numbers.
Version: 1.0.0
Oct. 4, 2025
-
Moved
v1.0.0-rc5
tov1.0.0
-
Tag name is
<bitty-1-0>
Version: 1.0.0-rc5
Oct. 4, 2025
-
Fixed bug with events not being passed to signal processing.
Version: 1.0.0-rc4
Oct. 1, 2025
-
Renamed
<bitty-js>
component tag to<bitty-MAJOR_VERSION>
for semantic versioning. -
Call
bittyInit()
withawait
if it's anasync
function. -
Moved
bittyInit()
before thedata-send
calls from the component so the module can set things up before the signals start being sent. -
Allowing
this.api.forward()
to be called with anull
event (e.g.this.api.forward(null, "anotherFunction");
). This is done to allow things like forwarding a signal frombittyInit()
or any other function where there isn't an event to pass along. -
Fixed bug where new receivers weren't being added properly when they were child nodes of new nodes being added (and the top layer didn't have a
data-
attr in it) -
Added tests for
this.api.querySelector()
anddocument.querySelector()
-
Update site to use variables for version numbers to make them easier to maintain instead of having them in multiple places for different displays.
-
Made
this.metadata
an object and movedversion
into it (along withcopyright
andlicense
)
Version: 1.0.0-rc3
Sept. 23, 2025
-
Fixed bug where
this.api.send()
would update thedata-send
attribute on the original element so it no longer send the same signal. The method is now calledthis.api.forward()
. -
Removed
data-watch
. Any element can receive a signal from anywhere else on the page without extra overhead. The biggest negative to this approach is that you have to be a little more careful to avoid naming collisions. But, the ease of use is well worth that minor trade off. -
Added Test Suite Results Report to site for easier viewing.
-
Applying passed and failed colors to individual tests for quicker scanning.
-
Updated tests to use unique signal names to avoid collisions.
Version: 1.0.0-rc2
Sept. 19, 2025
-
data-watch
is applied tobitty-js
elements directly instead of individual elements. The signals are send back down the tree when one is received viadata-watch
-
Refactored multiple UUID() calls to single function to save a few characters.
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
-
Flipped module arguments from
example(el, event)
toexample(event, el)
since that lines up better with the order of send/receive. (i.e. theevent
is what gets sent fromdata-send
and theel
is the element fromdata-receive
-
Remove HTML output of error message. They're nice during debug but wouldn't want them showing up in prod. Could use a
debug
flag but that's more overhead than I want to add. So, message just go to the console.
Version: 0.3.0
Sept. 17, 2025
Big refactor based on experience using 0.2.0.
-
Added more generic error handing where you just send a message and it outputs to the page along with the UUID of the element that had the problem. The elements have
bitty-js-error
style classes on them so their display can be controlled via CSS. -
Updated to use the name
data-connect
instead ofdata-module
-
The
data-connect
can point to either a module or to a class in a globalbittyClasses
window object. -
Alternate module classes are selected by passing a
|
followed by the desired class name instead of usingdata-use
. (e.g.data-connect="./module.js|AltClass
) -
If there's an
bittyInit()
function in a module it's the first thing that gets called once bitty is loaded. -
Removed
data-call
. Thedata-send
attribute is used for everything. Nothing would fire from it in prior versions if there wasn't at least one element with adata-receive
with the same name. Now it calls the function once with no element if there's no associateddata-receive
-
Added test suite.
-
The biggest update is changing
data-b
,data-c
,data-r
, anddata-s
todata-batch
,data-call
,data-receive
, anddata-send
, respectively. I originally use the shorter names to reduce the text length. The increased clarity of the longer names is worth the few extra characters. -
Remove expanded error messages. They were nice, but added a bunch of size without a significant improvement.
-
The other big change is removing the leading
_
and$
characters from function names. They were originally put in place to create a naming convention that differentiated between functions that were hit withdata-call
anddata-send
. In practice, that wasn't necessary. -
Removed the
data-batch
attribute. While there are some use cases where it might be nice, the extra complexity, mental overhead, and maintance aren't worth it. -
Added Mutation Observer so data-* functionality works on elements that are added after initialization.
-
Added Mutation Observer to watch for removed elements to pull them out of the mix when they get gone.
-
Split the web site page up into individual template for sections. Much nicer to work with.
-
Updated example functions to always use
(el, _event)
instead of(el, _)
for clarity. -
Removed inert/include/ignore from the top level components then remove them. This was originally a way to tell parent components to ignore specific calls and signals from children. After using it a bit, I don't think the complexity is worth it. Better to just name functions an signals so they don't collide.
-
Isolated default signal travel to only go down the DOM. That is, if there are nested bitty-js tags, signals from the child tags don't propagate to the parent by default. (see
data-watch
for how to send signals up and to siblings) -
Added
data-watch
so parents and siblings can receive signals from their children and other siblings. With this, signals can be sent up, down, and to siblings. -
Ignore events directly from
bitty-js
elements (i.e. only process events from child elements). This is done to preventdata-send
attributes onbitty-js
elements from firing repeatedly when things inside the element send events (e.g. clicks). -
Renamed
scripts
directory tomodules
. -
Moved bitty source script file under
bitty-versions/bitty-v0.3.0.js
and copying to prod at the root of the site (i.e./bitty-v0.3.0.js
) so examples look cleaner. -
Renamed
data-bridge
todata-connect
for clarity. -
Renamed
this.widget.bridge
tothis.module.api
inbitty-js
-
Added
this.api.send(key, event)
to send/forward events from inside modules. -
Added Progressive Enhancement and JavaScript Data comparison examples.
-
Added/polished a bunch of other examples.
Version: 0.2.3
June 5, 2025
Lots of error handling work in this one.
-
Moved UUID generation for the
bitty-js
and alldata-*
reactive elements to the first thing inconnectedCallback()
to aid in error messaging. -
Made
connectedCallback()
andasync
function to throw loading the widget module into its own funcitoun -
Created an
#errors
private var to store error messages and help by ID. - Added the first few error messages
-
Added
this.error()
for outputting errors. It takes two optional arguments: an ID and an Element. The ID maps to the IDs in#errors
. They're used to add detail and help message to the error output.The ID defaults to
0
which is an unclassified error type. The message for that ID includes a note to the developer to use an ID to classify the error. I consider it a bug if an appropriate ID doesn't exist and request an issue be open to fix it.The
this.error()
method dumps thebitty-js
elemnet after the message.If an element was passed to
this.error()
it's dumped out as well.The error message end up being pretty long. The end up adding a bunch of lines to the source file. That's an explicit decision aimed at making bitty easier to work with.
-
Added top level
debug
function that uses adebug
search query param from thewindow.location
to see if it should output.Only thing I don't like about it is that it shows the function's line number instead of the line number from where it was called. Something to look into.
-
The
debug
function takes an optional element. It dumps it to the console if one comes in. -
Renamed
data-wires
todata-bridge
. Fits better and maps nicer to the.bridge
coming back in from the support class. - Set up to load the default class exported from a widget module if no other class is defined (which happens with 'data-widget')
- Moved all examples to use a default class export instead of a named class
-
Added a
data-widget
attribute to thebitty-js
elements to allow using multiple classes from inside a single supporting .js module file. -
bitty-component-error
andbitty-element-error
classes are added to the class list of elements where errors occur.
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.
-
Added uuids as
data-uuid
attrs to all elements with relateddata-*
attributes. Added them to thebitty-js
elements too. I was originally thinking I'd add the UUIDs on the elements internally (i.e.el.uuid
instead ofel.dataset.uuid
).I decided on the attribute approach because it offers two benefits: 1. You can see the IDs in the Element tree view of developer consoles, and 2. You can address them with CSS to update styles based on the UUID. Both of those thing will go to supporting better error messages and bug hunting.
- Mostly content updates largely focused on detailing the opening counter example.
- Added CONTRIBUTING file.
- Added watcher script to build site when files change.
-
Refined the initial counter example to remove the text and change the
private variable to
this.num
to make the examples look nicer. - Moved the Examples section directly below the initial basic functionality overview section.
- Added reminders all over the place to edit the template and instead of the output for HTML page (which would be overwritten. ask me how I know).
-
Started adding
prettier-ignore
comments to code snippets to prevent the display output from being mangled. -
Started stripping
prettier-ignore
comments from the HTML output so it doesn't show in the example - Same goes for
// deno-fmt-ignore-file
in .js files - Added script to maintain the open open/closed states of the section details elements across page loads. (Having them close every time I made a change was maddening)
-
Moved all the example
.js
files into the site root. Not a fan of that in general, but it makes the examples look better since the path is shorter.
Version: 0.2.1
June 3, 2025
Some more wiring and some support tools for making the demo/docs site.
- Made a Hello, World example that shows basic features. (Compared to the single button press from the prior first example.)
- Showing Hello, World code as part of the example.
- Load templates automatically.
- Throttling via
.requestAnimationFrame()
. -
Renamed
data-f
todata-c
(i.e. "call") for clarity. -
Renamed
data-prep
attribute onbitty-js
tag todata-call
(i.e. "call") for clarity. -
Renamed
data-init
attribute onbitty-js
tag todata-send
so it matchesdata-s
more closely. - Made basic site builder for landing page.
-
Moved everything into
details
elements for the landing page.
Version: 0.2.0
June 3, 2025
Setting up a bunch of the basic wiring.
-
Rewrite to provide direct access to receiving elements. They are fully
accessible in the send/receive functions. (As compared to the 0.1.0
approach which required explicitly defining what would happen via an
update (e.g. update
.innerHTML
or.value
). -
Renamed
data-wrapper
and the targetWrapper
class todata-wires
andWires
. (bitty.js
is the wrapper. TheWires
class is how things are hooked up.). -
Added
data-call
attribute parsing tobitty-js
tag. It runs functions likedata-c
but does so prior to adding the event listeners to the element. -
Added
data-batch
attribute processing tobitty-js
tags. It operates likedata-b
but fires before event listeners are added. -
Added
data-ignore
attribute to allow components to avoid calls to the named functions. (Send signals bubble up to parents of nested components by default. This provides a way to ignore them). -
The
bitty-js
element looks for an.init()
method in theWires
class. If it finds one it calls it during the initialization process. - Passing both the element and the triggering event to the send/receive functions.
-
Moved to using
data-b
explicitly to separate block calls from individual function calls. - Order of operations is: function calls, batch calls, single send calls.
- Temporarily removed preflight check until global functionality is defined.
-
Created example of loading a template via the
.init()
call back to theWires
class. - Created example with nested components.
- Created example with parent of child components pulling data from the children to do a calculation.
- Created example showing parent ignoring send signals from children.
- Created example showing on components loading a child component via a template that becomes fully reactive.
Version: 0.1.0
June 2, 2025
Getting the project started.
-
Initial prototype.
-
<bitty-js>;
wraps elements to provide them with reactive capabilities. -
Basic
data-c
,data-s
, anddata-r
in place to call functions, send, and receive updates, respectively. -
Functionality is loaded using
data-wrapper
to point to a module to load. The module must export aWrapper
class that gets loaded and used to provide functions and send/receive callbacks. -
Uses string prefixes to make determinations about how to handle data through the send/receive channels (e.g.
htmlSOMETHING
updates.innerHTML
of an element whilevalueSOMETHING
updates the.value
). -
Defined convention for functions.
data-c
maps to functions in theWrapper
class that start with a_
(underscore). Thedata-s
anddata-r
attributes map to functions in theWrapper
class that start with a$
(dollar sign). -
Decided against using
data-c data-s and data-r
on thebitty.js
tags. That would involved a lot of extra overhead in parsing to differentiate between the top level element and the content it wraps. Usingdata-send
instead as a replacement fordata-c
. Others, TBD. -
Set up
data-c="batchSOMETHIGN"
functionality to send a single single that gets turned into multiple signals in theWrapper
. -
Defined convention of using
.batches
to look for batches. It must be a hash where the keys match the incoming request and the value is an array of functions to run. -
Defined
.bridge
to allowWrapper
functions to access the parentbitty-js
element. -
Scoped event listeners to the
bitty-js
elements. -
Set up
data-listeners
attribute onbitty-js
tags to override the default listeners (which areinput
andclick
). -
Created example that stores its own state.
-
Created example that updates an element with the same content it sent (i.e. verified feedback can be avoided).
-
Created example using
data-send
to load initial values. -
Created example that sends multiple signals.
-
Created example with multiple elements receiving the same signal.
-
Created example showing how to update global CSS variables/properties.
-
Created example showing custom event listeners.
-
Created example showing how to update CSS variables/properties scoped to the content of individual
bitty-js
tags. -
Examples use parent page's CSS for styling. It confirms I'm happy with the choice to use the light DOM instead of the shadow DOM.
-
Set up initial preflight check to ensure functions are in place.
Test Suite
Test Results
bittyInit is called automatically
Test Code
ID: 0005-bitty-init-is-called
FAILED
Basic Send and Receive
Test Code
ID: 0010-basic-send-receive
Test Trigger
FAILED
Nest Element Sending and Receiveing
- FAILED
Test Code
ID: 0015-nestined-send-and-receive
Test Trigger
---
FAILED
Send from the bitty-1-1 element
Test Code
ID: 0020-send-from-bitty-js
FAILED
Multiple sends from a single element
Test Code
ID: 0030-send-multiple-signals
Test Trigger
FAILED
FAILED
FAILED
Multiple Receivers for a Single Sender
Test Code
ID: 0040-multiple-receivers
Test Trigger
FAILED
FAILED
FAILED
Access data-* Attributes from Sending Elements
Test Code
ID: 0050-accessing-data-from-sending-element
Test Trigger
FAILED
Access data-* Attributes from Receiving Elements
Test Code
ID: 0060-access-data-from-receiving-element
Test Trigger
FAILED
Sending Many Signals to Many Receivers
Test Code
ID: 0070-many-sends-to-many-receivers
Test Trigger
FAILED
FAILED
FAILED
Forward an Event Inside a Module
Test Code
ID: 0075-forward-inside-module
Test Trigger
FAILED
Storing State
Test Code
ID: 0080-storing-state
Test Trigger
FAILED
Sending and Receiving from the Same Element
Test Code
ID: 0090-updating-self-loopback-signal
Test Trigger
Get Event Type
Test Code
ID: 0100-get-event-type
Test Trigger
FAILED
Verify UUIDs are Created on Sending Elements
Test Code
ID: 0110-verify-uuids-exist-on-senders
Test Trigger
FAILED
Verify UUIDs are Created on Receiving Elements
Test Code
ID: 0120-verify-uuids-exist-on-receivers
Test Trigger
FAILED
Verify UUIDs Exist On All Elements
Test Code
ID: 0125-uuids-exist-on-all-elements
FAILED
Verify UUIDs Are Added To Events
Test Code
ID: 0127-uuids-exist-on-events
Test Trigger
FAILED
Existing data-uuid Attributes Aren't Overwritten
Test Code
ID: 0128-uuids-are-not-overwritten
FAILED
FAILED
Ensure New Elements Get a data-uuid if They Have data-send/receive
Test Code
ID: 0130-create-an-element
Test Trigger
FAILED
Ensure Elements Made from Templates Get UUIDs
Test Code
ID: 0140-ensure-template-elements-get-uuids
Test Trigger
FAILED
const template = document.;
template. =
`<div><div><button class="test" data-send="testStub">FAILED</button></div></div>`;
Verify the bittyInit() Function Explicitly
Test Code
ID: 0160-init-function-works
FAILED
Use data-send To Call a Function When There's No Element With a Corresponding Receiver
Test Code
ID: 0170-use-data-send-without-a-receiver
Test Trigger
FAILED
Chain this.api.forward() calls
Test Code
ID: 0220-chain-forword-api-calls
Test Trigger
FAILED
FAILED
FAILED
FAILED
// Ensure the `data-send` value of the
// event generating element doesn't
// get changed
Forward Multiple Signals
Test Code
ID: 0230-forward-multiple-signals
Test Trigger
FAILED
FAILED
FAILED
FAILED
Call bittyInit() with await if it's async
Test Code
ID: 0250-async-bitty-init
FAILED
Use this.api.querySelector()
Test Code
ID: 0260-use-api-query-selector
FAILED
Documnet query selector
Test Code
ID: 0270-use-document-query-selector
FAILED
Test Trigger
Forward a Signal Without an Event
Test Code
ID: 0280-forward-without-event
FAILED
Check init Order
Test Code
ID: 0290-check-init-order
FAILED
Load New Node Receivers
Test Code
ID: 0300-load-new-nodes
Test Trigger
FAILED
Load Default window.BittyClass from Page (Manual Test)
Test Code
ID: 0330-load-default-page-class
waiting
Test Trigger
// This test comes from `window.BittyClass`
// on the parent HTML page.
Load Specific Class From window.BittyClasses (Manual Test)
Test Code
ID: 0340-load-directly-from-page
waiting
Test Trigger
// This test comes from `window.BittyClasses`
// on the parent HTML page.
Change Event Listeners
Test Code
ID: 0350-change-event-listeners
Test Target For Mouseover
Manual Test By Mousing Over
Nested bitty data-send does not bubble
Test Code
ID: 0360-nested-send-does-not-bubble
PASSED
Parent
Child
bitty element data-send uses bittysend event
Test Code
ID: 0370-bittysend-event
FAILED
Forward bitty tag data-send event
Test Code
ID: 0380-forwart-bitty-tag-send
FAILED
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