Object IDs in StringTune
Every element you activate with string becomes a managed StringObject. Each object carries a unique identifier so modules, mirrors, and your own code can reference it without ambiguity. This guide explains how those IDs are assigned, the different ways you can control them, and the common places they appear across the framework.
Why IDs Matter
StringTune leans on IDs to keep features deterministic:
- Event routing – Module events are namespaced by object ID (
object:progress:<id>,magnetic:move:<id>, etc.). Stable IDs let you subscribe without walking the DOM. - Mirror connections – Elements with
string-copy-from="<id>"attach themselves to the primary object identified by that ID. - State lookups –
stringTune.objectManager.all(internal) and debugging overlays surface objects by ID, making it easy to inspect which modules are attached. - Authoring clarity – Complex pages often reuse the same component multiple times; explicit IDs prevent animation timelines from bleeding between instances.
Default Behaviour
- When the engine discovers an element with
[string](ordata-string), it creates aStringObjectand assigns an auto-incremented ID likestring-1,string-2, etc. - The final ID is written back to the DOM as
string-id="string-1"so you can inspect it from devtools or target it in CSS ([string-id="string-hero"] {...}). - The attribute
string-initedis added automatically once the object is registered. Removing it or thestringattribute will cause the object to be disconnected.
Auto IDs are perfect for demos or simple pages, but production setups benefit from declaring IDs yourself.
Declaring Custom IDs
Add string-id (or its data-prefixed sibling) directly on the element before StringTune starts:
<section string="progress|parallax" string-id="hero" class="hero">...</section>
<!-- Works identically; useful for frameworks that reserve bare attributes -->
<section data-string="progress" data-string-id="pricing"></section>
Guidelines:
- IDs must be unique per page. Duplicates will cause later objects to reuse earlier instances.
- Use kebab-case or snake_case consistently—bus events simply append the string verbatim.
- Reserve predictable IDs for components rendered on both the server and client so hydration keeps references aligned.
Referencing IDs from Markup
| Feature | Attribute | What It Does | Example |
|---|---|---|---|
| Mirrors | string-copy-from | Links an auxiliary element to an existing object so it mirrors progress, easing, and CSS variables. | <div string-copy-from="hero"></div> |
| Scoped selectors | [string-id="..."] | Handy for styling or debugging a specific object once StringTune writes the attribute. | [string-id="cta"] { border: 1px solid var(--accent); } |
| Dataset linkage | data-string-id | Same as string-id, but survives HTML sanitizers that strip unknown attributes. | <article data-string="progress" data-string-id="story"></article> |
When a mirror connects successfully, StringTune also writes string-mirror-id on the mirrored element. That ID is generated automatically and rarely needs to be touched manually.
Subscribing to Module Events by ID
All module-level events include the object ID as the last segment. A few common patterns:
| Event | Emitted By | Payload | When It Fires |
|---|---|---|---|
object:progress:<id> | StringProgress | { progress: number } | Every frame while the element sits inside the progress window. |
object:parallax:<id> | StringParallax | { y: number } | Whenever the element's translation updates. |
magnetic:move:<id> | StringMagnetic | { x: number, y: number } | On each frame of magnetic motion. |
cursor:start:<id> / cursor:end:<id> | StringCursor | null | Pointer begins moving or stops moving over the target. |
cursor:move:<id> | StringCursor | { x: number, y: number } | Normalized coordinates change beyond epsilon. |
cursor:pixel:<id> | StringCursor | { x: number, y: number } | Smoothed pixel offsets update beyond epsilon. |
cursor | StringCursor | { x: number, y: number, stepX: number, stepY: number } | Global smoothed cursor position changes. |
object:activate:<id> | Core engine | boolean | Intersection observer toggles the object in or out of view. |
Hook into them with the global event bus:
import StringTune, { StringProgress, StringParallax } from '@fiddle-digital/string-tune';
const stringTune = StringTune.getInstance();
stringTune.use(StringProgress);
stringTune.use(StringParallax);
stringTune.start(60);
stringTune.on('object:progress:hero', ({ progress }) => {
console.log('Hero timeline:', progress.toFixed(2));
});
stringTune.on('object:parallax:hero', ({ y }) => {
heroSection.style.transform = `translateY(${y}px)`;
});
Need to replace listeners later? Call
stringTune.off('object:progress:hero', handler)or give the subscription anidargument when registering.
Accessing Objects Imperatively
If you are authoring a custom module or debugging a specific element, you can reuse the existing StringObject instead of creating duplicates:
import StringTune from '@fiddle-digital/string-tune';
const stringTune = StringTune.getInstance();
const hero = stringTune['objectManager'].all.get('hero');
if (hero) {
// Stored properties are available via getProperty
const start = hero.getProperty<number>('start-position');
console.log('Hero starts at', start);
}
The object manager is not part of the public API yet, so treat this as an advanced technique. Prefer bus events whenever possible—they stay stable across releases.
ID Hygiene Checklist
- Define IDs in templates for any element you plan to mirror, target with JavaScript, or reference in CSS.
- Avoid reusing IDs when you clone DOM nodes dynamically; clone the markup and update the value first.
- Watch server rendering: ensure SSR outputs the same attributes the client expects (
string-idordata-string-id). - Log undefined events: if your listener never fires, confirm the rendered ID matches the string in your subscription.
- Leverage mirrors sparingly: too many
string-copy-fromlinks pointing to a single heavy object can introduce layout thrash.
With intentional IDs, StringTune’s declarative attributes stay predictable, and the event bus becomes an ergonomic extension of your animation toolkit.