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 lookupsstringTune.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] (or data-string), it creates a StringObject and assigns an auto-incremented ID like string-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-inited is added automatically once the object is registered. Removing it or the string attribute 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

FeatureAttributeWhat It DoesExample
Mirrorsstring-copy-fromLinks 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 linkagedata-string-idSame 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:

EventEmitted ByPayloadWhen 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>StringCursornullPointer 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.
cursorStringCursor{ x: number, y: number, stepX: number, stepY: number }Global smoothed cursor position changes.
object:activate:<id>Core enginebooleanIntersection 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 an id argument 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-id or data-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-from links 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.