7.1 KiB
NodeEditor.js API Documentation
NodeEditor.js is a lightweight, framework-agnostic, zero-dependency node editor library written in pure ES6 JavaScript. It leverages standard DOM elements for high-performance node manipulation and an SVG overlay plane for drawing scalable Bezier connections.
🚀 Quick Start
1. HTML Setup
Create a dedicated target container for the editor. Ensure the container has explicit dimensional bounds (width and height).
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Node Editor Instance</title>
<style>
body { margin: 0; background: #111; }
#editor-container {
width: 100vw;
height: 100vh;
}
</style>
</head>
<body>
<div id="editor-container"></div>
<script type="module" src="./app.js"></script>
</body>
</html>
2. JavaScript Initialization (app.js)
Import the NodeEditor module, hook it to your DOM node, and instantiate your first pipeline.
import { NodeEditor } from './NodeEditor.js';
// 1. Initialize the UI Engine
const container = document.getElementById('editor-container');
const editor = new NodeEditor(container);
// 2. Extract the State Manager
const graph = editor.getGraphManager();
// 3. Spawning Nodes
const nodeA = graph.addNode({
type: 'source_node',
title: 'Data Stream',
x: 100,
y: 150,
inputs: [],
outputs: [{ id: 'out_raw', name: 'Raw Buffer' }]
});
const nodeB = graph.addNode({
type: 'processing_node',
title: 'Transform Matrix',
x: 450,
y: 250,
inputs: [{ id: 'in_data', name: 'Payload' }],
outputs: [{ id: 'out_success', name: 'Success' }]
});
// 4. Create a programmatically driven wire connection
graph.connect(nodeA.id, 'out_raw', nodeB.id, 'in_data');
🛠️ Architecture Overview
The library enforces a strict separation of concerns via an asynchronous, decoupled state cycle:
[User Action / UI Pointer Interaction]
│
▼
[GraphManager State Engine] ◄─── (Single Source of Truth)
│
▼ (Dispatches Event Hub Actions)
[NodeEditor Render Architecture]
│
┌──────────┴──────────┐
▼ ▼
[DOM Element Nodes] [SVG Vector Overlay Patches]
📚 API Reference
NodeEditor (UI Controller)
The wrapper orchestration manager that structures layout elements, listens to user viewport transforms, and monitors state bindings.
new NodeEditor(containerElement)Instantiates a fresh node pipeline map inside a target DOM container.editor.getGraphManager()Returns the underlying dataGraphManagerengine operating behind the target instance.editor.updateAllConnections()Forces an absolute layout recalculation of all connection nodes in view. Useful if you change node positions outside the lifecycle API or resize your external container dynamically.
GraphManager (State Controller)
The isolated data engine that processes, updates, validates, and serializes graph states.
Node Management APIs
addNode(config)Registers a new data node. Returns the instantiatedNodeSchemaobject.config.title: (String) Header title text.config.x/config.y: (Numbers) Absolute starting canvas positioning.config.inputs/config.outputs: Array of port objects ({ id: 'unique_port_id', name: 'Display Name' }).config.id: (Optional) Provide a deterministic string ID; otherwise, an internal generic system identifier will be automatically assigned.
deleteNode(nodeId)Destroys the node element matching the identifier and automatically sweeps/prunes any associated broken dependency lines.updateNodePosition(nodeId, x, y)Mutates raw positioning values inside the memory reference model and triggers view updating layers.
Connection Management APIs
connect(fromNodeId, fromSocketId, toNodeId, toSocketId)Wires an active logical curve bridge between an output port and an input port. ReturnsConnectionSchemaobject ornullif the connection is illegal (e.g. self-looping or double mapping onto an input).disconnect(connectionId)Severs a trace path across nodes using its direct line identifier.
Serialization & Hydration
getState()Returns a deep, JSON-serializable clone of the entire active workspace graph network topology.loadState(graphState)Clears all active rendered interface objects and loads a freshly mappedGraphStateconfiguration layer.
// Saving state to local storage
const currentSnapshot = graph.getState();
localStorage.setItem('my_graph', JSON.stringify(currentSnapshot));
// Restoring state later
const cachedSnapshot = JSON.parse(localStorage.getItem('my_graph'));
if (cachedSnapshot) {
graph.loadState(cachedSnapshot);
}
🎛️ Handling Graph Events
The GraphManager implements a lightweight publisher/subscriber layout. You can listen to lifecycle changes across your pipeline engine to trigger custom code:
// Capture changes to map properties to external reactive modules
graph.on('stateChanged', (latestState) => {
console.log("Global modifications registered:", latestState);
});
// Trace isolated edge terminations
graph.on('connectionRemoved', (connId) => {
console.warn(`Connection item vanished from runtime: ${connId}`);
});
// Trace node structural changes
graph.on('nodeAdded', (node) => {
console.log(`New node generated: ${node.title}`);
});
Available Event Signatures
| Event Key | Callback Arguments | Description |
|---|---|---|
'nodeAdded' |
(nodeSchema) |
Dispatched when a node object joins the topology. |
'nodeRemoved' |
(nodeId) |
Dispatched when a node is removed from the canvas. |
'nodeMoved' |
(nodeSchema) |
Dispatched repeatedly when a node object moves coordinates. |
'connectionAdded' |
(connectionSchema) |
Dispatched when two nodes are connected. |
'connectionRemoved' |
(connectionId) |
Dispatched when an edge bridge is broken or deleted. |
'stateChanged' |
(graphState) |
Global catch-all event executed immediately after any graph mutation. |
⌨️ User Interface Interactions
- Pan Canvas: Click and drag anywhere on the empty background or the SVG connection space.
- Zoom Viewport: Scroll your mouse wheel or trackpad up and down. The transformation framework calculates and pins vector values centered directly on your mouse cursor location.
- Drag Nodes: Click and hold the node header bar container element. Movement velocities match your active zoom ratio precisely.
- Draw Wires: Click a target circular socket connector on an output node and drag your mouse. Drop the temporary dashed wire onto a target input node socket to complete a bridge connection.
- Destroy Wires: Click directly on an active solid colored connection bridge path vector line to delete it from the running memory structure.
- Destroy Nodes: Click the small
✕button positioned inside the upper-right corner of the node header frame.