
Enter a search term above to see results...
Enter a search term above to see results...
Query can be extended with custom functionality using two approaches:
Query plugins extend Query instances by adding methods to Query.prototype
via $.plugin
:
The $.plugin
object is an alias for Query.prototype
. Methods added here become available on all Query instances with full access to chaining and the Query API. Use plugins for utility methods that don’t require state management or complex configuration.
Query behaviors use registerBehavior()
for interactive patterns with settings, events, and state management. The registerBehavior()
function accepts multiple configuration options for creating feature-rich behaviors:
Use behaviors when building interactive components that need state management, configuration options, or complex event handling.
Registration Behaviors should self-register through side-effect imports, enabling modular architecture where
import '@semantic-ui/query/behaviors/transition'
makes the behavior available across your application.
The following is an example of initialization a new behavior with all available options:
import { registerBehavior } from '@semantic-ui/query';
registerBehavior({ // Core configuration name: 'tooltip', defaultSettings: { showDelay: 0 },
// Configurable selectors and classes selectors: { trigger: '.tooltip-trigger', content: '.tooltip-content' }, classNames: { visible: 'visible', hidden: 'hidden' },
// Plugin methods createBehavior: ({ settings, self }) => ({ show() { /* implementation */ }, hide() { /* implementation */ }, toggle() { /* implementation */ } }),
// Event handlers with templating support events: { 'mouseenter {trigger}': ({ self }) => self.show(), 'mouseleave': ({ self }) => self.hide() }});
// Usage$('ui-icon.help').tooltip({ showDelay: 200 });$('ui-icon.help').tooltip('show');
The name
defines the plugin identifier and method name created on Query instances:
registerBehavior({ name: 'tooltip'});
// Creates method available on all Query instances$('ui-icon.help').tooltip();
The namespace
controls where the plugin instance is stored on DOM elements (defaults to name
):
registerBehavior({ name: 'tooltip', namespace: 'myTooltip' // Stored as element.myTooltip instead of element.tooltip});
Default settings establish the base configuration that gets inherited and merged with user-provided settings and data attributes:
const defaultSettings = { showDelay: 300, trigger: 'hover'};
$('ui-icon.help').tooltip({ showDelay: 100 });// Result: { showDelay: 100, trigger: 'hover' }
<ui-icon class="help" data-trigger="click"></ui-icon><!-- Final result: { showDelay: 100, trigger: 'click' } -->
See Plugin Usage for runtime configuration and override examples.
Returns an object with methods that become callable on plugin instances:
const createBehavior = ({ settings, self }) => ({ show() { self.$tooltip.addClass('visible'); settings.onShow?.(); },
hide() { self.$tooltip.removeClass('visible'); settings.onHide?.(); },
toggle() { return self.isVisible() ? self.hide() : self.show(); },
isVisible() { return self.$tooltip.hasClass('visible'); }});
Call methods using string syntax:
$('ui-icon.help').tooltip('show');$('ui-icon.help').tooltip('toggle state'); // Finds toggleState()$('ui-icon.help').tooltip('is visible'); // Finds isVisible()const visible = $('ui-icon.help').tooltip('get status'); // Finds getStatus() or get.status
For direct access, call plugin methods on DOM elements:
const el = document.querySelector('ui-icon.help');el.tooltip.show(); // Direct method call, different coding style
Method Lookup Supports natural language patterns:
'toggle state'
findstoggleState()
ortoggle.state()
, trying camelCase conversion first, then dot notation traversal.
Runs once during plugin registration and returns shared resources for all instances:
const setup = ({ $, templates }) => ({ $overlay: $('<div class="tooltip-overlay">').appendTo('body'), cache: new Map()});
Shared resources become properties on self
, available in createBehavior
and all plugin methods:
const createBehavior = ({ self }) => ({ show() { // These properties came from setup() return value self.$overlay.addClass('visible'); self.cache.set('lastShown', Date.now()); }});
Setup Connection Whatever you return from
setup()
becomes properties on theself
object, automatically available to all plugin instances and methods.
Setup Arguments Receives different parameters than other callbacks:
{ $, settings, $elements, templates }
- note the plural$elements
since setup runs before individual instances are created.
Plugins use configuration objects to define constants that can be overridden by users for customization and internationalization:
registerBehavior({ name: 'tooltip', selectors: { trigger: '.tooltip-trigger' // Configurable DOM selectors }, classNames: { visible: 'visible' // Configurable CSS classes }, errors: { noTarget: 'No target element found' // Localizable error messages }, templates: { tooltip: '<div class="tooltip"></div>' // Reusable HTML templates }});
These objects are available in all plugin callbacks and can be used in event strings with templating:
createBehavior: ({ self, templates, errors }) => ({ show() { if (!self.$tooltip) { self.$tooltip = $(templates.tooltip).appendTo('body'); } self.$tooltip.addClass('visible'); }}),
events: { 'click {trigger}': ({ self, errors }) => { if (!self.hasTarget()) { console.error(errors.noTarget); return; } self.toggle(); }}
Users can override defaults for customization or localization:
// Custom selectors and templates$('.my-tooltip').tooltip({ selectors: { trigger: '.custom-trigger' }, templates: { tooltip: '<div class="custom-tooltip"></div>' }});
// Localized error messages and templates$.tooltip.errors.noTarget = 'Aucun élément cible trouvé';$.tooltip.templates.loading = '<div>Chargement...</div>';
Behaviors can inject CSS styles automatically when they’re registered. The css
property accepts a string of CSS that gets added to the page as a constructed stylesheet:
registerBehavior({ name: 'tooltip',
css: ` /* other css */ .tooltip.visible { opacity: 1; } `,
createBehavior: ({ self, classNames }) => ({ show() { self.$tooltip.addClass(classNames.visible); } })});
The CSS is cached and reused across behavior instances for performance. This means multiple tooltip elements will share the same stylesheet rather than duplicating styles.
Constructed Stylesheets Query uses the browser’s Constructed Stylesheet API for efficient style injection. Styles are automatically scoped and cleaned up when no longer needed.
Declarative event handlers with automatic delegation:
Event Delegation Event handlers are attached using delegation where the behavior listens for bubbled events. This means events will fire even if matching elements are added or removed after initialization.
const events = { 'mouseenter': ({ self, settings }) => { self.showTimer = setTimeout(self.show, settings.showDelay); },
'mouseleave': ({ self, settings }) => { self.hideTimer = setTimeout(self.hide, settings.hideDelay); },
'click .close': ({ self }) => { self.hide(); },
'global scroll': ({ self }) => { self.updatePosition(); }};
'click'
- Event on behavior element'click .selector'
- Delegated event within behavior element'bind focus input'
- Direct binding to subelements (for non-bubbling custom events)'global scroll'
- Global event on any element outside the behaviorEvent strings support templating using configuration objects. Use {key}
syntax to reference selectors
, classNames
and settings
:
registerBehavior({ settings: { trigger: '.tooltip-trigger', }, events: { 'click {trigger}': ({ self }) => { // Uses settings.trigger (also works with class names and selectors) self.toggle(); } }});
Events are automatically cleaned up when behavior instances are destroyed using an AbortController when your behavior is destroyed or you call .behaviorName('destroy')
.
Watch for DOM changes using declarative mutation observers:
registerBehavior({ name: 'dynamicList',
mutations: { 'add .item': ({ $added }) => { $added.addClass('new-item'); },
'remove .item': ({ $removed }) => { console.log('Items removed:', $removed.length); } }});
Mutation strings support templating using configuration objects. Use {key}
syntax to reference selectors
, classNames
and settings
:
registerBehavior({ settings: { mutatingElement: 'li', // watch for li changes }, mutations: { '{mutatingElement}': ({ self }) => { // do something } }});
This example uses a templated mutation observer to watch for new list items and add markdown formatting.
.item
- Watch for any .item elements added or removedadd .item
- Only trigger when .item elements are addedremove .item
- Only trigger when .item elements are removedobserve .container => .item
- Watch .container for .item changesattributes .element
- Watch for attribute changes on .elementtext .element
- Watch for text content changes in .elementMutation strings support templating using configuration objects, just like events:
registerBehavior({ selectors: { listItem: '.dynamic-item' },
mutations: { 'add {listItem}': ({ $added, self }) => { // Uses selectors.listItem self.initializeItems($added); } }});
Mutation observers are automatically disconnected when behavior instances are destroyed.
The customInvocation
callback handles method calls that don’t match any defined behavior methods, enabling flexible string-based APIs:
registerBehavior({ name: 'transition',
createBehavior: ({ self }) => ({ performTransition(type, duration) { /* implementation */ } }),
customInvocation: ({ methodName, methodArgs, self }) => { // Route transition names to implementation return self.performTransition(methodName, ...methodArgs); }});
// Usage$('.modal').transition('fade in', 500); // Calls customInvocation$('.modal').transition('slide up', 300); // Calls customInvocation
This enables Semantic UI-style APIs where string arguments can trigger different behaviors without requiring exact method name matches.
Run code during behavior creation and destruction:
registerBehavior({ onCreated: ({ el, settings }) => { console.log('Behavior created on', el); },
onDestroyed: ({ el }) => { console.log('Behavior destroyed on', el); // Cleanup code here }});
Behavior callbacks like createBehavior
, onCreated
, and event handlers receive destructurable parameters to access shared state, DOM elements, and behavior context.
The self
parameter is the behavior instance itself - it contains all methods returned from createBehavior()
plus any shared resources from setup()
. This allows methods to call each other and access shared state.
All callbacks receive consistent base parameters:
Parameter | Description |
---|---|
$ | Query constructor function |
el | Raw DOM element the behavior is attached to |
$el | Query wrapper for the behavior element |
self | Behavior instance with methods and shared resources |
plugin | Alias for self |
namespace | Behavior namespace (usually same as name) |
data | Element data attributes parsed as native values |
selectors | Behavior selector mappings |
errors | Behavior error message mappings |
classNames | Behavior CSS class mappings |
settings | Current behavior settings (merged defaults + user settings) |
Event handlers receive all base parameters plus:
Parameter | Description |
---|---|
event | Event object |
target | Event target element |
value | Element value (from input, event.target, or event.detail) |
data | Combined element data attributes + event detail data |
Setup callback receives different parameters:
Parameter | Description |
---|---|
$ | Query constructor function |
settings | Behavior default settings |
$elements | Query collection of elements (plural) |
templates | HTML templates object |
// Initialize with defaults$('.behavior').behavior();
// With custom settings$('.behavior').behavior({ delay: 100, trigger: 'hover'});
Call methods via Query with natural language support:
$('ui-icon.help').tooltip('show');$('ui-icon.help').tooltip('toggle state'); // Finds toggleState()
Access behavior instances directly on DOM elements:
const el = document.querySelector('ui-icon.help');el.tooltip.show(); // Direct method call
Bridge Query selection with direct method calls:
$('ui-icon.help').el().tooltip.isVisible(); // Query → DOM → direct call
Query intelligently collects return values from multiple elements:
const states = $('ui-icon.help').tooltip('is visible'); // [true, false, true]
// Update settings after initialization (triggers re-initialization)$('ui-icon.help').tooltip({ showDelay: 200, trigger: 'click'});
HTML data attributes automatically override behavior and user settings. This can be controlled with allowDataOverride
:
registerBehavior({ name: 'tooltip', allowDataOverride: false // Prevents data-* attributes from overriding settings});
When enabled (default), HTML data attributes override settings:
<!-- These override any JavaScript settings --><ui-icon class="help" data-show-delay="500" data-trigger="focus"></ui-icon><ui-icon class="help" data-complex-setting='{"enabled": true, "count": 3}'></ui-icon>
Attribute names use kebab-case and are automatically converted to camelCase settings.
// Modify defaults for all future instances$.tooltip.defaultSettings.showDelay = 100;
Return Values Behavior methods can return values, and Query intelligently collects them - single values for one element, arrays for multiple elements, with automatic deduplication.