or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

core-management.mdelement-collections.mdevent-system.mdextensions.mdgraph-algorithms.mdindex.mdlayout-system.mdstyling-system.md
tile.json

event-system.mddocs/

Event System

Rich event system supporting user interactions, element lifecycle events, viewport changes, and custom events with delegation, namespacing, and promise-based handling.

Capabilities

Event Binding and 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

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;
}

User Input Events

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 released

Usage 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();
  }
});

Collection Events

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 changed

Usage 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());
});

Graph Events

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 resized

Usage 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
});

Event Namespacing

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');

Event Delegation

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');
});

Promise-Based Event Handling

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');
  });

Custom Events

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);
});

Event Performance and Best Practices

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);
});

Event Bubbling and Propagation

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