Rich event system supporting user interactions, element lifecycle events, viewport changes, and custom events with delegation, namespacing, and promise-based handling.
Bind event handlers to core instance and element collections.
interface Core {
/**
* Bind event handler
* @param events - Space-separated event names
* @param selector - Optional element selector for delegation
* @param handler - Event handler function
* @returns Core instance for chaining
*/
on(events: string, selector?: string, handler?: EventHandler): Core;
on(events: string, handler: EventHandler): Core;
/**
* Bind one-time event handler
* @param events - Space-separated event names
* @param selector - Optional element selector for delegation
* @param handler - Event handler function
* @returns Core instance for chaining
*/
one(events: string, selector?: string, handler?: EventHandler): Core;
one(events: string, handler: EventHandler): Core;
/**
* Unbind event handler
* @param events - Event names (optional, unbinds all if not specified)
* @param selector - Element selector (optional)
* @param handler - Handler function (optional, unbinds all matching if not specified)
* @returns Core instance for chaining
*/
off(events?: string, selector?: string, handler?: EventHandler): Core;
off(events?: string, handler?: EventHandler): Core;
/**
* Trigger event
* @param events - Space-separated event names
* @param extraParams - Additional parameters to pass to handlers
* @returns Core instance for chaining
*/
emit(events: string, extraParams?: any[]): Core;
/**
* Promise-based event binding (resolves on first event)
* @param events - Space-separated event names
* @returns Promise that resolves when event occurs
*/
pon(events: string): Promise<Event>;
/**
* Remove event listener (alias for off)
* @param events - Event names
* @param selector - Element selector
* @param handler - Handler function
* @returns Core instance for chaining
*/
removeListener(events?: string, selector?: string, handler?: EventHandler): Core;
}
interface Collection {
/**
* Bind event handler to collection elements
* @param events - Space-separated event names
* @param handler - Event handler function
* @returns Collection for chaining
*/
on(events: string, handler: EventHandler): Collection;
/**
* Bind one-time event handler
* @param events - Space-separated event names
* @param handler - Event handler function
* @returns Collection for chaining
*/
one(events: string, handler: EventHandler): Collection;
/**
* Unbind event handler
* @param events - Event names (optional)
* @param handler - Handler function (optional)
* @returns Collection for chaining
*/
off(events?: string, handler?: EventHandler): Collection;
/**
* Trigger event on collection elements
* @param events - Space-separated event names
* @param extraParams - Additional parameters
* @returns Collection for chaining
*/
trigger(events: string, extraParams?: any[]): Collection;
/**
* Promise-based event binding
* @param events - Space-separated event names
* @returns Promise that resolves when event occurs
*/
pon(events: string): Promise<Event>;
}
interface EventHandler {
(event: Event): void;
}Event object passed to event handlers contains contextual information.
interface Event {
/**
* Element that triggered the event
*/
target: Collection;
/**
* Event type name
*/
type: string;
/**
* Model position where event occurred
*/
position: Position;
/**
* Rendered (screen) position where event occurred
*/
renderedPosition: Position;
/**
* Cytoscape instance
*/
cy: Core;
/**
* Original browser event (for user events)
*/
originalEvent?: MouseEvent | TouchEvent | KeyboardEvent;
/**
* Namespace for the event
*/
namespace?: string;
/**
* Additional data passed with event
*/
data?: any;
/**
* Timestamp when event occurred
*/
timeStamp: number;
}Events triggered by user interactions with mouse, touch, and keyboard.
/**
* Mouse events
*/
type MouseEventType =
| "mousedown" // Mouse button pressed
| "mouseup" // Mouse button released
| "click" // Mouse click
| "dblclick" // Double click
| "mouseover" // Mouse enters element
| "mouseout" // Mouse leaves element
| "mousemove" // Mouse moves over element
| "rightclick"; // Right mouse button click
/**
* Touch events
*/
type TouchEventType =
| "touchstart" // Touch begins
| "touchmove" // Touch moves
| "touchend"; // Touch ends
/**
* Normalized gesture events (work for both mouse and touch)
*/
type GestureEventType =
| "tap" // Single tap/click
| "tapstart" // Tap/click begins
| "tapend" // Tap/click ends
| "tapdrag" // Drag during tap
| "taphold" // Long press/hold
| "cxttap"; // Context tap (right-click or long tap)
/**
* Keyboard events
*/
type KeyboardEventType =
| "keydown" // Key pressed down
| "keyup" // Key released
| "keypress"; // Key pressed and releasedUsage Examples:
// Basic click handler
cy.on('tap', 'node', function(evt) {
const node = evt.target;
console.log('Tapped node:', node.id());
console.log('Position:', evt.position);
});
// Mouse hover effects
cy.on('mouseover', 'node', function(evt) {
evt.target.style('background-color', 'red');
});
cy.on('mouseout', 'node', function(evt) {
evt.target.removeStyle('background-color');
});
// Touch handling
cy.on('taphold', 'node', function(evt) {
console.log('Node held for long press');
});
// Keyboard shortcuts
cy.on('keydown', function(evt) {
if (evt.originalEvent.key === 'Delete') {
cy.$(':selected').remove();
}
});Events related to element lifecycle and state changes.
/**
* Lifecycle events
*/
type LifecycleEventType =
| "add" // Element added to graph
| "remove" // Element removed from graph
| "move"; // Element moved to different location
/**
* Selection events
*/
type SelectionEventType =
| "select" // Element selected programmatically
| "unselect" // Element unselected programmatically
| "tapselect" // Element selected by user tap
| "tapunselect" // Element unselected by user tap
| "boxselect" // Elements selected by box selection
| "boxunselect"; // Elements unselected by box selection
/**
* Interaction events
*/
type InteractionEventType =
| "grab" // Node grabbed for dragging
| "drag" // Node being dragged
| "free" // Node released from dragging
| "lock" // Node locked (position fixed)
| "unlock"; // Node unlocked
/**
* Data events
*/
type DataEventType =
| "data" // Element data changed
| "scratch" // Element scratch data changed
| "style" // Element style changed
| "position"; // Element position changed
/**
* Class events
*/
type ClassEventType =
| "class"; // Element classes changedUsage Examples:
// Handle element additions
cy.on('add', 'node', function(evt) {
const node = evt.target;
console.log('Node added:', node.id());
// Apply default styling to new nodes
node.style('background-color', '#666');
});
// Track selection changes
cy.on('select', 'node', function(evt) {
console.log('Selected:', evt.target.id());
});
cy.on('unselect', function(evt) {
console.log('Unselected:', evt.target.id());
});
// Handle dragging
cy.on('grab', 'node', function(evt) {
evt.target.style('background-color', 'red');
});
cy.on('free', 'node', function(evt) {
evt.target.removeStyle('background-color');
});
// Monitor data changes
cy.on('data', function(evt) {
console.log('Data changed on:', evt.target.id());
});Events related to the graph as a whole, including viewport and layout changes.
/**
* Viewport events
*/
type ViewportEventType =
| "pan" // Viewport panned
| "zoom" // Viewport zoomed
| "viewport"; // Viewport changed (pan or zoom)
/**
* Layout events
*/
type LayoutEventType =
| "layoutstart" // Layout started running
| "layoutready" // Layout positions calculated
| "layoutstop"; // Layout finished running
/**
* Core events
*/
type CoreEventType =
| "ready" // Graph fully initialized
| "destroy" // Graph instance destroyed
| "render" // Graph rendered/redrawn
| "resize"; // Container resizedUsage Examples:
// Handle viewport changes
cy.on('zoom', function(evt) {
console.log('Zoom level:', cy.zoom());
});
cy.on('pan', function(evt) {
console.log('Pan position:', cy.pan());
});
// Layout progress tracking
cy.on('layoutstart', function(evt) {
console.log('Layout started:', evt.layout.options.name);
// Show loading indicator
});
cy.on('layoutstop', function(evt) {
console.log('Layout finished');
// Hide loading indicator
});
// Graph initialization
cy.on('ready', function(evt) {
console.log('Graph ready');
// Perform initial setup
});Use namespaces to organize and manage event handlers.
/**
* Namespaced event syntax: "eventname.namespace"
*/
// Bind namespaced events
cy.on('tap.myPlugin', 'node', handler1);
cy.on('tap.myPlugin', 'edge', handler2);
cy.on('select.myPlugin', handler3);
// Unbind all events in namespace
cy.off('.myPlugin');
// Unbind specific namespaced event
cy.off('tap.myPlugin');
// Trigger namespaced event
cy.emit('customEvent.myNamespace');Use selectors to handle events on specific element types without binding to each element.
// Event delegation - handles all current and future nodes
cy.on('tap', 'node', function(evt) {
// This handler applies to all nodes, even ones added later
console.log('Node tapped:', evt.target.id());
});
// Multiple selectors
cy.on('tap', 'node.important, edge.highlighted', function(evt) {
console.log('Important element tapped');
});
// Complex selectors
cy.on('tap', 'node[type="user"]', function(evt) {
console.log('User node tapped');
});Use promises for one-time event handling and async workflows.
/**
* Promise-based event binding
*/
// Wait for next tap event
cy.pon('tap').then(function(evt) {
console.log('Tap occurred on:', evt.target.id());
});
// Wait for layout completion
cy.pon('layoutstop').then(function() {
console.log('Layout finished');
// Continue with next step
});
// Async/await syntax
async function waitForSelection() {
const evt = await cy.pon('select');
console.log('Selected:', evt.target.id());
return evt.target;
}
// Chain promise events
cy.pon('tap')
.then(() => cy.pon('layoutstop'))
.then(() => {
console.log('Tap and layout both completed');
});Create and trigger custom events for application-specific logic.
// Trigger custom events
cy.emit('myCustomEvent', [{ customData: 'value' }]);
// Listen for custom events
cy.on('myCustomEvent', function(evt, data) {
console.log('Custom event triggered with:', data);
});
// Element-specific custom events
const node = cy.$('#myNode');
node.trigger('nodeSpecificEvent', [{ nodeData: node.data() }]);
node.on('nodeSpecificEvent', function(evt, data) {
console.log('Node event with data:', data);
});Optimize event handling for better performance.
// Use event delegation instead of binding to many elements
// Good:
cy.on('tap', 'node', handler);
// Avoid:
cy.nodes().on('tap', handler);
// Batch event bindings
cy.batch(function() {
cy.on('tap', 'node', handler1);
cy.on('tap', 'edge', handler2);
cy.on('select', handler3);
});
// Clean up event handlers when done
function cleanup() {
cy.off('.myApp'); // Remove all namespaced handlers
}
// Throttle or debounce high-frequency events
let panTimeout;
cy.on('pan', function() {
clearTimeout(panTimeout);
panTimeout = setTimeout(function() {
// Handle pan end
console.log('Pan finished');
}, 100);
});Understand event flow and control propagation.
// Events bubble from target to parent elements
cy.on('tap', 'node', function(evt) {
console.log('Node tapped');
// Stop event from bubbling to parent
evt.stopPropagation();
});
// Core-level handler (receives all events)
cy.on('tap', function(evt) {
console.log('Something was tapped:', evt.target);
});
// Event order: specific selector handlers first, then general handlers