When Components Become State Machines
Once Bootstrap's layout rules have placed a control, the harder problem is what happens over time. This chapter examines Bootstrap's JavaScript as a stateful layer: how a plugin is activated, how it owns an element, how events and transitions move it between states, and where focus, security, and framework integration constrain the result. A modal provides the clearest case, because its visible panel depends on several pieces of page behavior that a class name alone cannot coordinate.
A plugin has two entry points but one lifecycle
Bootstrap offers two ways to start most JavaScript plugins. A data attribute lets the HTML describe the relationship: a button can identify itself as a control for a dropdown, collapse region, modal, or another supported component. The programmatic API lets JavaScript construct a plugin, pass options, retrieve an existing instance, or create one if it does not yet exist. These are two entry points into the same behavior layer, not two separate implementations. Both eventually need an element, configuration, state, event handling, and cleanup.
That shared lifecycle is important when a page grows beyond a demo. Declarative markup is often the clearest choice for a straightforward control whose configuration belongs near its HTML. Programmatic construction is useful when the target is chosen dynamically, options come from application state, or code needs to react to completion events. Neither entry point changes the fact that an interactive component has an owner. Someone must decide which element is controlled, which configuration is active, and what happens when the component is removed or replaced.
Bootstrap's shared base component makes that ownership concrete. It resolves the target element, merges configuration with values supplied by the element, checks the resulting types, and stores the plugin instance against that element. A project can then ask for the instance associated with an element or use a get-or-create operation. Disposal removes the stored data and event handlers and clears the component's own references. The purpose is not merely convenience. It gives the plugin a recognizable identity and a termination path instead of allowing each activation to create an untracked copy.
The data layer enforces an additional rule: Bootstrap does not allow more than one instance per element under its current model. This prevents two copies of the same plugin, or incompatible plugin state, from silently competing for one target. The rule can surface as an error when code tries to attach another instance. That is a useful failure because the alternative is harder to diagnose: one handler opens a component while another handler reads stale configuration or closes it unexpectedly.
Events make the lifecycle observable and interruptible. Bootstrap generally names an event for the beginning of an action and another for its completion, such as show and shown. The beginning event is cancellable, so application code can prevent an action before it changes the page. The completion event is the place to run work that depends on the transition having finished. This distinction avoids a common timing error: treating a method call as proof that the visual and accessibility state is already complete.
The methods are asynchronous in the practical sense that they return after a transition starts, not after it ends. A second method call while a component is transitioning can be ignored. That rule simplifies the component's internal state, but it also creates an obligation for callers. Code that needs to act after an animation or cleanup must listen for the corresponding completion event rather than immediately issuing a dependent call.