### Local LiteGraph.js Setup and Server Start Source: https://github.com/jagenjo/litegraph.js/blob/master/README.md Provides the command-line steps to clone the LiteGraph.js repository, install dependencies, and start the local development server. This is used to run the demo applications. ```shell $ git clone https://github.com/jagenjo/litegraph.js.git $ cd litegraph.js $ npm install $ node utils/server.js Example app listening on port 80! ``` -------------------------------- ### start Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/classes/LGraph.html Starts the graph execution at a specified interval. ```APIDOC ## start ### Description Starts the graph execution at a specified interval. ### Method Not specified (assumed to be a method call on an LGraph object) ### Parameters #### Path Parameters None #### Query Parameters None #### Parameters * **interval** (Number) - The interval in milliseconds between executions. If 0, it runs at the monitor's refresh rate. ### Request Example ```javascript graph.start(interval); ``` ### Response None explicitly documented. ``` -------------------------------- ### start Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/files/.._src_litegraph.js.html Starts the graph execution loop. The graph will run at the monitor's refresh rate if interval is 0, otherwise it runs at the specified interval in milliseconds. ```APIDOC ## start ### Description Starts running this graph every interval milliseconds. ### Method `start(interval)` ### Parameters #### Path Parameters - **interval** (number) - Amount of milliseconds between executions. If 0, it renders to the monitor refresh rate. ``` -------------------------------- ### Install LiteGraph.js using npm Source: https://github.com/jagenjo/litegraph.js/wiki/First-Project Use this command to install the LiteGraph.js library via npm. Ensure you have Node.js and npm installed. ```bash npm install litegraph.js ``` -------------------------------- ### Example C++ Code Snippet Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/assets/vendor/prettify/README.html This is an example of C++ code that will be prettified. It demonstrates basic class definition and static constants. ```cpp class Voila { public: // Voila static const string VOILA = "Voila"; // will not interfere with embedded [tags](#voila1). } ``` -------------------------------- ### startRendering Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/classes/LGraphCanvas.html Starts the rendering loop for the canvas, enabling continuous updates. ```APIDOC ## startRendering ### Description Initiates the continuous rendering loop for the canvas, ensuring that the graph is redrawn as needed. ### Method `startRendering()` ``` -------------------------------- ### Example C++ Code Snippet (with different tag) Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/assets/vendor/prettify/README.html This is another example of C++ code, similar to the previous one but with a different tag reference, demonstrating how prettifying handles distinct code blocks. ```cpp class Voila { public: // Voila static const string VOILA = "Voila"; // will not interfere with embedded [tags](#voila2). } ``` -------------------------------- ### startRendering Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/classes/LGraphCanvas.html Starts rendering the content of the canvas when needed. ```APIDOC ## startRendering ### Description Starts rendering the content of the canvas when needed. ### Method (Not specified, likely a method call on an LGraphCanvas instance) ### Parameters (No parameters specified in the source) ### Response (No response specified in the source) ``` -------------------------------- ### Start Graph Execution Source: https://github.com/jagenjo/litegraph.js/blob/master/index.html Begin the execution of the graph. This will process the nodes and their connections. ```javascript graph.start(); ``` -------------------------------- ### Full Custom Node Example Source: https://github.com/jagenjo/litegraph.js/wiki/Creating-custom-Nodes This is a complete example of a custom 'Sum' node in LiteGraph.js, combining constructor, properties, execution logic, and registration. ```javascript //node constructor class function MyAddNode() { this.addInput("A", "number"); this.addInput("B", "number"); this.addOutput("A+B", "number"); } //name to show MyAddNode.title = "Sum"; MyAddNode.position = [10, 50]; MyAddNode.size = [300, 50]; //function to call when the node is executed MyAddNode.prototype.onExecute = function() { var A = this.getInputData(0); if (A === undefined) A = 0; var B = this.getInputData(1); if (B === undefined) B = 0; this.setOutputData(0, A + B); } //register in the system LiteGraph.registerNodeType("basic/sum", MyAddNode); ``` -------------------------------- ### Start Graph Execution Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/files/.._src_litegraph.js.html Starts the graph execution loop. If interval is 0, it uses requestAnimationFrame for optimal rendering. Otherwise, it uses setInterval with the specified interval in milliseconds. ```javascript LGraph.prototype.start = function( interval ) { if( this.status == LGraph.STATUS_RUNNING ) return; this.status = LGraph.STATUS_RUNNING; if(this.onPlayEvent) this.onPlayEvent(); this.sendEventToAllNodes("onStart"); //launch this.starttime = LiteGraph.getTime(); this.last_update_time = this.starttime; interval = interval || 0; var that = this; if(interval == 0 && typeof(window) != "undefined" && window.requestAnimationFrame ) { function on_frame() { if(that.execution_timer_id != -1) return; window.requestAnimationFrame(on_frame); that.runStep(1, !that.catch_errors ); } this.execution_timer_id = -1; on_frame(); } else this.execution_timer_id = setInterval( function() { //execute that.runStep(1, !that.catch_errors ); },interval); } ``` -------------------------------- ### Server-Side Graph Initialization Source: https://github.com/jagenjo/litegraph.js/blob/master/README.md Demonstrates how to initialize and run a LiteGraph.js graph on the server using NodeJS. Requires the LiteGraph.js module to be installed. ```javascript var LiteGraph = require("./litegraph.js").LiteGraph; var graph = new LiteGraph.LGraph(); var node_time = LiteGraph.createNode("basic/time"); graph.add(node_time); var node_console = LiteGraph.createNode("basic/console"); node_console.mode = LiteGraph.ALWAYS; graph.add(node_console); node_time.connect( 0, node_console, 1 ); graph.start() ``` -------------------------------- ### Basic LiteGraph.js Project Setup Source: https://github.com/jagenjo/litegraph.js/blob/master/README.md This HTML structure sets up a canvas and initializes a basic LiteGraph.js graph with a constant node and a watch node, connecting them. ```html ``` -------------------------------- ### Start Canvas Rendering Loop Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/files/.._src_litegraph.js.html Starts the animation frame rendering loop for the canvas. It uses `requestAnimationFrame` for efficient rendering and calls the `draw` method on each frame unless paused. ```javascript LGraphCanvas.prototype.startRendering = function() { if(this.is_rendering) return; //already rendering this.is_rendering = true; renderFrame.call(this); function renderFrame() { if(!this.pause_rendering) this.draw(); var window = this.getCanvasWindow(); if(this.is_rendering) window.requestAnimationFrame( renderFrame.bind(this) ); } } ``` -------------------------------- ### Include Prettify Script and Stylesheets Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/assets/vendor/prettify/README.html Include the necessary CSS and JavaScript files in your HTML document. Adjust the paths to match your server setup. ```html ``` -------------------------------- ### Connect Nodes Source: https://github.com/jagenjo/litegraph.js/blob/master/index.html Establish a connection between two nodes in the graph. This example connects the output of the constant node to the input of the watch node. ```javascript node_const.connect(0, node_watch, 0 ); ``` -------------------------------- ### Basic LiteGraph.js Example Source: https://github.com/jagenjo/litegraph.js/wiki/First-Project This HTML and JavaScript code creates a simple graph with a constant node and a watch node, demonstrating basic node creation, positioning, connection, and graph execution. ```html ``` -------------------------------- ### Add Nodes to the Graph Source: https://github.com/jagenjo/litegraph.js/blob/master/index.html Create and add nodes to the graph. This example adds a constant node and a watch node. ```javascript var node_const = LiteGraph.createNode("basic/const"); node_const.pos = [200,200]; graph.add(node_const); node_const.setValue(4.5); var node_watch = LiteGraph.createNode("basic/watch"); node_watch.pos = [700,200]; graph.add(node_watch); ``` -------------------------------- ### Enable Line Numbers with Starting Line Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/assets/vendor/prettify/README.html To display line numbers, add the `linenums` class to your code block. You can specify a starting line number by appending it after a colon, like `linenums:4`. ```html
// This is line 4.
foo();
bar();
baz();
boo();
far();
faz();
```

--------------------------------

### Create a Custom Node in LiteGraph.js

Source: https://github.com/jagenjo/litegraph.js/blob/master/guides/README.md

Example of creating a custom node by defining its constructor, inputs, outputs, properties, and execution logic. This node performs addition.

```javascript
function MyAddNode()
{
  //add some input slots
  this.addInput("A","number");
  this.addInput("B","number");
  //add some output slots
  this.addOutput("A+B","number");
  //add some properties
  this.properties = { precision: 1 };
}

//name to show on the canvas
MyAddNode.title = "Sum";

//function to call when the node is executed
MyAddNode.prototype.onExecute = function()
{
  //retrieve data from inputs
  var A = this.getInputData(0);
  if( A === undefined )
    A = 0;
  var B = this.getInputData(1);
  if( B === undefined )
    B = 0;
  //assing data to outputs
  this.setOutputData( 0, A + B );
}

//register in the system
LiteGraph.registerNodeType("basic/sum", MyAddNode );

```

--------------------------------

### Get Output Connection Information

Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/files/.._src_litegraph.js.html

Retrieves information about an output slot, including its name, type, and the IDs of connected links.

```javascript
LGraphNode.prototype.getOutputInfo = function(slot)
{
	if(!this.outputs)
		return null;
	if(slot < this.outputs.length)
		return this.outputs[slot];
	return null;
}
```

--------------------------------

### Get Input Connection Information

Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/files/.._src_litegraph.js.html

Retrieves detailed information about an input connection, including the link ID, name, and type.

```javascript
LGraphNode.prototype.getInputInfo = function(slot)
{
	if(!this.inputs)
		return null;
	if(slot < this.inputs.length)
		return this.inputs[slot];
	return null;
}
```

--------------------------------

### Node Clipping Area Setup

Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/files/.._src_litegraph.js.html

Sets up the clipping area for a node based on its shape (box, rounded, or circle). This ensures that content drawn outside the node's bounds is not visible.

```javascript
if( node.clip_area ) //Start clipping
{
	ctx.save();
	ctx.beginPath();
	if(shape == LiteGraph.BOX_SHAPE)
		ctx.rect(0,0,size[0], size[1]);
	else if (shape == LiteGraph.ROUND_SHAPE)
		ctx.roundRect(0,0,size[0], size[1],10);
	else if (shape == LiteGraph.CIRCLE_SHAPE)
		ctx.arc(size[0] * 0.5, size[1] * 0.5, size[0] * 0.5, 0, Math.PI*2);
	ctx.clip();
}
```

--------------------------------

### Render Spline Connections

Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/files/.._src_litegraph.js.html

Renders connections using Bezier curves when the link render mode is set to SPLINE_LINK. It calculates control points based on start and end directions.

```javascript
if(this.links_render_mode == LiteGraph.SPLINE_LINK)
		{
			ctx.moveTo(a[0],a[1] + offsety);
			var start_offset_x = 0;
			var start_offset_y = 0;
			var end_offset_x = 0;
			var end_offset_y = 0;
			switch(start_dir)
			{
				case LiteGraph.LEFT: start_offset_x = dist*-0.25; break;
				case LiteGraph.RIGHT: start_offset_x = dist*0.25; break;
				case LiteGraph.UP: start_offset_y = dist*-0.25; break;
				case LiteGraph.DOWN: start_offset_y = dist*0.25; break;
			}
			switch(end_dir)
			{
				case LiteGraph.LEFT: end_offset_x = dist*-0.25; break;
				case LiteGraph.RIGHT: end_offset_x = dist*0.25; break;
				case LiteGraph.UP: end_offset_y = dist*-0.25; break;
				case LiteGraph.DOWN: end_offset_y = dist*0.25; break;
			}
			ctx.bezierCurveTo(a[0] + start_offset_x, a[1] + start_offset_y + offsety,
								b[0] + end_offset_x , b[1] + end_offset_y + offsety,
								b[0], b[1] + offsety);
		}
```

--------------------------------

### Initialize and Control HTML Console

Source: https://github.com/jagenjo/litegraph.js/blob/master/editor/editor_mobile.html

Sets up the HTML console, maps console.log and console.debug to the custom console, and adds event listeners for toggling visibility and clearing the console.

```javascript
if(editorUseHtmlConsole){
    elem.querySelector("#btn_console").addEventListener("click", function(){
        var consoleCnt = document.getElementById('console-container');
        if (consoleCnt.classList.contains("invisible")){
            consoleCnt.classList.remove("invisible");
        }else{
            jsConsole.clean();
            consoleCnt.classList.add("invisible");
        }
    });

    const params = {
        expandDepth : 1,
        common : {
            excludeProperties : ["__proto__"],
            removeProperties: ["__proto__"],
            maxFieldsInHead : 5,
            minFieldsToAutoexpand : 5,
            maxFieldsToAutoexpand : 15
        }
    };

    var jsConsole = new Console(document.querySelector('.console-container'), params);
    jsConsole.log("Here is console.log!");

    // map console log-debug to jsConsole
    console.log = function(par){
        jsConsole.log(par);
        var objDiv = document.getElementById("console-container");
        objDiv.scrollTop = objDiv.scrollHeight;
    }
    console.debug = console.log;

    console.log("going into html console");

    document.getElementById("btn_console_clear").addEventListener("click", function(){
        var consoleCnt = document.getElementById('console-container');
        jsConsole.clean();
    });

    document.getElementById("btn_console_close").addEventListener("click", function(){
        var consoleCnt = document.getElementById('console-container');
        consoleCnt.classList.add("invisible");
    });
}
```

--------------------------------

### Get Time Implementation for LiteGraph.js

Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/files/.._src_litegraph.js.html

Provides a cross-environment compatible function to get the current time. It prioritizes `performance.now()`, falls back to `Date.now()`, and uses `process.hrtime()` in Node.js environments, ensuring consistent timing across different platforms.

```javascript
//timer that works everywhere
if(typeof(performance) != "undefined")
	LiteGraph.getTime = performance.now.bind(performance);
else if(typeof(Date) != "undefined" && Date.now)
	LiteGraph.getTime = Date.now.bind(Date);
else if(typeof(process) != "undefined")
	LiteGraph.getTime = function(){
		var t = process.hrtime();
		return t[0]*0.001 + t[1]*(1e-6);
	}
else
  LiteGraph.getTime = function getTime() { return (new Date).getTime(); }
```

--------------------------------

### getConnectionPos

Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/classes/LGraphNode.html

Gets the canvas coordinates of a connection point.

```APIDOC
## getConnectionPos

### Description
Returns the center of a connection point in canvas coordinates.

### Parameters
* `is_input` (Boolean) - True if it's an input slot, false if it's an output slot.
* `slot` (Number_or_string) - The number or name of the slot.
* `out` (Vec2) - [Optional] A vector to store the output position, to avoid garbage collection.

### Returns
x,y: The coordinates of the connection point.
```

--------------------------------

### configure

Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/classes/LGraph.html

Configures the graph from a JSON string, loading its structure and node states.

```APIDOC
## configure

### Description
Configures the graph from a JSON string, loading its structure and node states.

### Signature
`configure(str, returns)`

### Parameters
*   **str** (String) - The JSON string containing the graph configuration.
*   **returns** (Boolean) - Indicates if there was any error during parsing. Returns `true` if there was an error, `false` otherwise.
```

--------------------------------

### Create Node via Context Menu

Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/files/.._src_litegraph.js.html

Handles the creation of new nodes through a context menu. It first displays node categories, then specific node types within a category, and finally creates the node at the mouse position.

```javascript
LGraphCanvas.onMenuAdd = function( node, options, e, prev_menu )
{
	var canvas = LGraphCanvas.active_canvas;
	var ref_window = canvas.getCanvasWindow();

	var values = LiteGraph.getNodeTypesCategories();
	var entries = [];
	for(var i in values)
		if(values[i])
			entries.push({ value: values[i], content: values[i], has_submenu: true });

	//show categories
	var menu = new LiteGraph.ContextMenu( entries, { event: e, callback: inner_clicked, parentMenu: prev_menu }, ref_window);

	function inner_clicked( v, option, e )
	{
		var category = v.value;
		var node_types = LiteGraph.getNodeTypesInCategory( category, canvas.filter );
		var values = [];
		for(var i in node_types)
			if (!node_types[i].skip_list)
				values.push( { content: node_types[i].title, value: node_types[i].type });

		new LiteGraph.ContextMenu( values, {event: e, callback: inner_create, parentMenu: menu }, ref_window);
		return false;
	}

	function inner_create( v, e )
	{
		var first_event = prev_menu.getFirstEvent();
		var node = LiteGraph.createNode( v.value );
		if(node)
		{
			node.pos = canvas.convertEventToCanvasOffset( first_event );
			canvas.graph.add( node );
		}
	}

	return false;
}
```

--------------------------------

### Get Output Data

Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/files/.._src_litegraph.js.html

Retrieves the last data that was output from a specific output slot.

```javascript
LGraphNode.prototype.getOutputData = function(slot)
{
	if(!this.outputs)
		return null;
	if(slot >= this.outputs.length)
		return null;

	var info = this.outputs[slot];
	return info._data;
}
```

--------------------------------

### Get Node by ID

Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/files/.._src_litegraph.js.html

Retrieves a node instance from the graph using its unique identifier.

```javascript
LGraph.prototype.getNodeById = function( id )
{
	if( id == null )
		return null;
	return this._nodes_by_id[ id ];
}
```

--------------------------------

### configure

Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/classes/LGraphNode.html

Configures a node from a serialized object.

```APIDOC
## configure

### Description
Configure a node from an object containing the serialized info.

### Returns
None
```

--------------------------------

### ContextMenu Constructor

Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/classes/ContextMenu.html

Constructs a new ContextMenu instance. This menu can be populated with various items, each potentially having a title, a callback function, and other properties. Options can customize the menu's appearance and behavior, such as setting a title, a general callback for item clicks, or specifying the event that triggered the menu.

```APIDOC
## ContextMenu Constructor

### Description
Constructs a new ContextMenu instance. This menu can be populated with various items, each potentially having a title, a callback function, and other properties. Options can customize the menu's appearance and behavior, such as setting a title, a general callback for item clicks, or specifying the event that triggered the menu.

### Method
Constructor

### Parameters:

* `values` (Array) - An array of items for the menu. Each item can be an object with properties like `title` and `callback`.
* `options` (Object) - Optional. Configuration options for the menu:
    * `title` (string) - The title to display at the top of the menu.
    * `callback` (function) - A function to be called when an item is clicked. It receives the item information.
    * `ignore_item_callbacks` (boolean) - If true, ignores the `callback` defined within individual menu items and only uses the `options.callback`.
    * `event` (MouseEvent) - A MouseEvent object. If provided, the menu will be positioned at the event's location.
```

--------------------------------

### Get Output Connected Nodes

Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/files/.._src_litegraph.js.html

Retrieves an array of all nodes connected to a specific output slot.

```javascript
LGraphNode.prototype.getOutputNodes = function(slot)
{
	if(!this.outputs || this.outputs.length == 0)
		return null;

	if(slot >= this.outputs.length)
		return null;

	var output = this.outputs[slot];
	if(!output.links || output.links.length == 0)
		return null;

	var r = [];
	for(var i = 0; i < output.links.length; i++)
	{
		var link_id = output.links[i];
		var link = this.graph.links[ link_id ];
		if(link)
		{
			var target_node = this.graph.getNodeById( link.target_id );
			if( target_node )
				r.push( target_node );
		}
	}
	return r;
}
```

--------------------------------

### Initialize LGraph and LGraphCanvas

Source: https://github.com/jagenjo/litegraph.js/blob/master/guides/README.md

Basic integration of LiteGraph.js into an HTML application by creating an LGraph instance and an LGraphCanvas instance.

```javascript
var graph = new LiteGraph.LGraph();
var graph_canvas = new LiteGraph.LGraphCanvas( canvas, graph );
```

--------------------------------

### Get Input Node

Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/files/.._src_litegraph.js.html

Retrieves the node connected to a specific input slot. Returns null if there is no connection or the link is invalid.

```javascript
LGraphNode.prototype.getInputNode = function( slot )
{
	if(!this.inputs)
		return null;
	if(slot >= this.inputs.length)
		return null;
	var input = this.inputs[slot];
	if(!input || input.link === null)
		return null;
	var link_info = this.graph.links[ input.link ];
	if(!link_info)
		return null;
	return this.graph.getNodeById( link_info.origin_id );
}
```

--------------------------------

### Initialize ContextMenu

Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/files/.._src_litegraph.js.html

Constructor for the ContextMenu class, used for creating interactive menus in the LiteGraph.js GUI. It accepts an array of values and an options object for customization.

```javascript
function ContextMenu( values, options )
{
	options = options || {};
	this.options = options;
	var that = this;

	//to link a menu with its parent
	if(options.parentMenu)
	{
		if( options.parentMenu.constructor !== this.constructor )
		{
			console.error("parentMenu must be of class ContextMenu, ignoring it");
			options.parentMenu = null;
		}
		else
		{
			this.parentMenu = options.parentMenu;
			this.parentMenu.lock = true;
			this.parentMenu.current_submenu = this;
		}
	}

	if(options.event && options.event.constructor !== MouseEvent && options.event.constructor !== CustomEvent)
	{
		console.error("Event passed to ContextMenu is not of type MouseEvent or CustomEvent. Ignoring it.");
		options.event = null;
	}

	var root = document.createElement("div");
	root.className = "litegraph litecontextmenu litemenubar-panel";
	if( options.className)
		root.className += " " + options.className;
	root.style.minWidth = 100;
	root.style.minHeight = 100;
	root.style.pointerEvents = "none";
	setTimeout( function() { root.style.pointerEvents = "auto"; },100); //delay so the mouse up event is not caugh by this element

	//this prevents the default context browser menu to open in case this menu was created when pressing right button
	root.addEventListener("mouseup", function(e){
		e.preventDefault(); return true;
	}, true);
	root.addEventListener("contextmenu", function(e) {
		if(e.button != 2) //right button
			return false;
		e.preventDefault();
		return false;
	},true);

	root.addEventListener("mousedown", function(e){
		if(e.button == 2)
		{
			that.close();
			e.preventDefault(); return true;
		}
	}, true);

	function on_mouse_wheel(e)
	{
		var pos = parseInt( root.style.top );
		root.style.top = (pos + e.deltaY * options.scroll_speed).toFixed() + "px";
		e.preventDefault();
		return true;
	}

	if(!options.scroll_speed)
		options.scroll_speed = 0.1;

	root.addEventListener("wheel", on_mouse_wheel, true);
	root.addEventListener("mousewheel", on_mouse_wheel, true);


	this.root = root;

	//title
	if(options.title)
	{
		var element = document.createElement("div");
		element.className = "litemenu-title";
		element.innerHTML = options.title;
		root.appendChild(element);
	}

	//entries
	var num = 0;
	for(var i in values)
	{
		var name = values.constructor == Array ? values[i] : i;
		if( name != null && name.constructor !== String )
			name = name.content === undefined ? String(name) : name.content;
		var value = values[i];
		this.addItem( name, value, options );
		num++;
	}

	//close on leave
	root.addEventListener("mouseleave", function(e) {
		if(that.lock)
			return;
		if(root.closing_timer)
			clearTimeout( root.closing_timer );
		root.closing_timer = setTimeout( that.close.bind(that, e), 500 );
		//that.close(e);
	});

	root.addEventListener("mouseenter", function(e) {
		if(root.closing_timer)
			clearTimeout( root.closing_timer );
	});

	//insert before checking position
	var root_document = document;
	if(options.event)
		root_document = options.event.target.ownerDocument;

	if(!root_document)
		root_document = document;
	root_document.body.appendChild(root);
}
```

--------------------------------

### Get Fixed Time Accumulation

Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/files/.._src_litegraph.js.html

Retrieves the accumulated time using the fixedtime_lapse variable, useful for constant time increments.

```javascript
LGraph.prototype.getFixedTime = function()
{
	return this.fixedtime;
}
```

--------------------------------

### getNodeType

Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/files/.._src_litegraph.js.html

Retrieves a registered node type by its name. This function allows you to get the class definition for a specific node type.

```APIDOC
## getNodeType

### Description
Retrieves a registered node type by its name. This function allows you to get the class definition for a specific node type.

### Method Signature
`getNodeType(type)`

### Parameters
*   **type** (String) - The full name of the node class (e.g., 'math/sin').

### Returns
*   (Class) - The node class definition, or undefined if the type is not registered.
```

--------------------------------

### Initialize Graph Properties

Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/files/.._src_litegraph.js.html

Initializes various timing, error catching, and data properties for the graph instance.

```javascript
this.globaltime = 0;
this.runningtime = 0;
this.fixedtime =  0;
this.fixedtime_lapse = 0.01;
this.elapsed_time = 0.01;
this.last_update_time = 0;
this.starttime = 0;

this.catch_errors = true;

//subgraph_data
this.inputs = {};
this.outputs = {};

//notify canvas to redraw
this.change();

this.sendActionToCanvas("clear");
```

--------------------------------

### Get Node Types by Category

Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/files/.._src_litegraph.js.html

Returns an array of node classes that belong to a specified category. An optional filter can be applied.

```javascript
getNodeTypesInCategory: function( category, filter )
{
	var r = [];
	for(var i in this.registered_node_types)
	{
		var type = this.registered_node_types[i];
		if(filter && type.filter && type.filter != filter)
			continue;

		if(category == "" )
		{
			if (type.category == null)
				r.push(type);
		}
		else if (type.category == category)
			r.push(type);
	}

	return r;
},
```

--------------------------------

### Create Node Instance

Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/files/.._src_litegraph.js.html

Creates a new node instance of a specified type. Handles potential exceptions during instantiation if `LiteGraph.catch_exceptions` is true. Initializes default properties for the node.

```javascript
createNode: function( type, title, options )
{
	var base_class = this.registered_node_types[type];
	if (!base_class)
	{
		if(LiteGraph.debug)
			console.log("GraphNode type \"" + type + "\" not registered.");
		return null;
	}

	var prototype = base_class.prototype || base_class;

	title = title || base_class.title || type;

	var node = null;

	if( LiteGraph.catch_exceptions )
	{
		try
		{
			node = new base_class( title );
		}
		catch (err)
		{
			console.error(err);
			return null;
		}
	}
	else
		node = new base_class( title );

	node.type = type;

	if(!node.title && title) node.title = title;
	if(!node.properties) node.properties = {};
	if(!node.properties_info) node.properties_info = [];
	if(!node.flags) node.flags = {};
	if(!node.size) node.size = node.computeSize();
	if(!node.pos) node.pos = LiteGraph.DEFAULT_POSITION.concat();
	if(!node.mode) node.mode = LiteGraph.ALWAYS;

		//extra options
	if(options)
	{
		for(var i in options)
			node[i] = options[i];
	}

	return node;
},
```

--------------------------------

### Create a Graph Instance

Source: https://github.com/jagenjo/litegraph.js/blob/master/index.html

Instantiate a new LGraph object to manage the graph structure.

```javascript
var graph = new LGraph();
```

--------------------------------

### Create a Canvas Renderer

Source: https://github.com/jagenjo/litegraph.js/blob/master/index.html

Initialize a canvas renderer for the graph, targeting a specific HTML element.

```javascript
var canvas = new LGraphCanvas("#mycanvas");
```

--------------------------------

### Get Top-Level Context Menu

Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/files/.._src_litegraph.js.html

Recursively traverses parent menus to return the root or top-most context menu in a nested structure.

```javascript
ContextMenu.prototype.getTopMenu = function()
{
	if( this.options.parentMenu )
		return this.options.parentMenu.getTopMenu();
	return this;
}
```

--------------------------------

### Get Input Data by Slot

Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/files/.._src_litegraph.js.html

Retrieves the data from a specific input slot. Handles cases where the slot is not connected or the link is invalid.

```javascript
if(slot >= this.inputs.length || this.inputs[slot].link == null)
		return null;
	var link_id = this.inputs[slot].link;
	var link = this.graph.links[ link_id ];
	if(!link) //bug: weird case but it happens sometimes
		return null;
	var node = this.graph.getNodeById( link.origin_id );
	if(!node)
		return link.type;
	var output_info = node.outputs[ link.origin_slot ];
	if(output_info)
		return output_info.type;
	return null;
}
```

--------------------------------

### Display Optional Node Outputs Menu

Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/files/.._src_litegraph.js.html

Shows a context menu for a node's optional outputs. It handles dynamic output generation and filtering of repeated outputs.

```javascript
LGraphCanvas.showMenuNodeOptionalOutputs = function( v, options, e, prev_menu, node )
{
	if(!node)
		return;

	var that = this;
	var canvas = LGraphCanvas.active_canvas;
	var ref_window = canvas.getCanvasWindow();

	var options = node.optional_outputs;
	if(node.onGetOutputs)
		options = node.onGetOutputs();

	var entries = [];
	if(options)
		for (var i in options)
		{
			var entry = options[i];
			if(!entry) //separator?
			{
				entries.push(null);
				continue;
			}

			if(node.flags && node.flags.skip_repeated_outputs && node.findOutputSlot(entry[0]) != -1)
				continue; //skip the ones already on
			var label = entry[0];
			if(entry[2] && entry[2].label)
				label = entry[2].label;
			var data = {content: label, value: entry};
			if(entry[1] == LiteGraph.EVENT)
				data.className = "event";
			entries.push(data);
		}

	if(this.onMenuNodeOutputs)
		entries = this.onMenuNodeOutputs( entries );

	if(!entries.length)
		return;

	var menu = new LiteGraph.ContextMenu(entries, {event: e, callback: inner_clicked, parentMenu: prev_menu, node: node }, ref_window);

	function inner_clicked( v, e, prev )
	{
		if(!node)
			return;

		if(v.callback)
			v.callback.call( that, node, v, e, prev );

		if(!v.value)
			return;

		var value = v.value[1];

		if(value && (value.constructor === Object || value.constructor === Array)) //submenu why?
		{
			var entries = [];
			for(var i in value)
				entries.push({ content: i, value: value[i]});
			new LiteGraph.ContextMenu( entries, { event: e, callback: inner_clicked, parentMenu: prev_menu, node: node });
			return false;
		}
		else
		{
			node.addOutput( v.value[0], v.value[1], v.value[2]);
			node.setDirtyCanvas(true,true);
		}

	}

	return false;
}
```

--------------------------------

### Configure Graph from JSON Data

Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/files/.._src_litegraph.js.html

Configures the graph using provided JSON data. Optionally clears the existing graph before configuration.

```javascript
LGraph.prototype.configure = function( data, keep_old )
{
	if(!data)
		return;

	if(!keep_old)
		this.clear();

	var nodes = data.nodes;

	//decode links info (they are very verbose)
	if(data.links && data.links.constructor === Array)
	{
		var links = [];
		for(var i = 0; i < data.links.length; ++i)
		{
			var link_data = data.links[i];
			var link = new LLink();
			link.configure( link_data );
			links[ link.id ] = link;
		}
		data.links = links;
	}

	//copy all stored fields
	for (var i in data)
		this[i] = data[i];

	var error = false;

	//create nodes
	this._nodes = [];
	if(nodes)
	{
		for(var i = 0, l = nodes.length; i < l; ++i)
		{
			var n_info = nodes[i]; //stored info
			var node = LiteGraph.createNode( n_info.type, n_info.title );
			if(!node)
			{
				if(LiteGraph.debug)
					console.log("Node not found or has errors: " + n_info.type);

				//in case of error we create a replacement node to avoid losing info
				node = new LGraphNode();
				node.last_serialization = n_info;
				node.has_errors = true;
				error = true;
				//continue;
			}

			node.id = n_info.id; //id it or it will create a new id
			this.add(node, true); //add before configure, otherwise configure cannot create links
		}

		//configure nodes afterwards so they can reach each other
		for(var i = 0, l = nodes.length; i < l; ++i)
		{
			var n_info = nodes[i];
			var node = this.getNodeById( n_info.id );
			if(node)
				node.configure( n_info );
		}
	}

	//groups
	this._groups.length = 0;
	if( data.groups )
	for(var i = 0; i < data.groups.length; ++i )
	{
		var group = new LiteGraph.LGraphGroup();
		group.configure( data.groups[i] );
		this.add( group );
	}

	this.updateExecutionOrder();
	this._version++;
	this.setDirtyCanvas(true,true);
	return error;
}
```

--------------------------------

### Get Global Input Data

Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/files/.._src_litegraph.js.html

Retrieves the current data associated with a global graph input. Returns null if the input is not found.

```javascript
LGraph.prototype.getInputData = function(name)
{
	var input = this.inputs[name];
	if (!input)
		return null;
	return input.value;
}
```

--------------------------------

### Get Group on Canvas Position

Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/files/.._src_litegraph.js.html

Finds the topmost group that contains the specified canvas coordinates. This is useful for interacting with grouped nodes.

```javascript
LGraph.prototype.getGroupOnPos = function(x,y)
{
	for (var i = this._groups.length - 1; i >= 0; i--)
	{
		var g = this._groups[i];
		if(g.isPointInside( x, y, 2, true ))
			return g;
	}
	return null;
}
```

--------------------------------

### Get Graph Execution Time

Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/files/.._src_litegraph.js.html

Returns the total time in milliseconds that the graph has been running. This is useful for timing-related operations within the graph.

```javascript
LGraph.prototype.getTime = function()
{
	return this.globaltime;
}
```

--------------------------------

### getOutputInfo

Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/classes/LGraphNode.html

Provides information about an output connection, including its name, type, and connected links.

```APIDOC
## getOutputInfo

### Description
Tells you info about an output connection (which node, type, etc).

### Parameters
* `slot` (Number) - The index of the output slot.

### Returns
* Object - An object containing connection info { name: string, type: string, links: [ids of links in number] }, or null if no connection exists.
```

--------------------------------

### Get Node Type by Name

Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/files/.._src_litegraph.js.html

Retrieves a registered node class using its full name. Returns null if the type is not found.

```javascript
getNodeType: function(type)
{
	return this.registered_node_types[type];
},
```

--------------------------------

### Get First Event Associated with Menu

Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/files/.._src_litegraph.js.html

Retrieves the initial event that triggered the context menu, traversing up the parent menu chain if necessary.

```javascript
ContextMenu.prototype.getFirstEvent = function()
{
	if( this.options.parentMenu )
		return this.options.parentMenu.getFirstEvent();
	return this.options.event;
}
```

--------------------------------

### Show Optional Node Inputs Menu

Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/files/.._src_litegraph.js.html

Displays a context menu for adding optional inputs to a node. It retrieves input options either from the node's `optional_inputs` property or by calling its `onGetInputs` method.

```javascript
LGraphCanvas.showMenuNodeOptionalInputs = function( v, options, e, prev_menu, node )
{
	if(!node)
		return;

	var that = this;
	var canvas = LGraphCanvas.active_canvas;
	var ref_window = canvas.getCanvasWindow();

	var options = node.optional_inputs;
	if(node.onGetInputs)
		options = node.onGetInputs();

	var entries = [];
	if(options)
		for (var i in options)
		{
			var entry = options[i];
			if(!entry)
			{
				entries.push(null);
				continue;
			}
			var label = entry[0];
			if(entry[2] && entry[2].label)
				label = entry[2].label;
			var data = {content: label, value: entry};
			if(entry[1] == LiteGraph.ACTION)
				data.className = "event";
			entries.push(data);
		}

	if(this.onMenuNodeInputs)
		entries = this.onMenuNodeInputs( entries );

	if(!entries.length)
		return;

	var menu = new LiteGraph.ContextMenu(entries, { event: e, callback: inner_clicked, parentMenu: prev_menu, node: node }, ref_window);

	function inner_clicked(v, e, prev)
	{
		if(!node)
			return;

		if(v.callback)
			v.callback.call( that, node, v, e, prev );

		if(v.value)
		{
			node.addInput(v.value[0],v.value[1], v.value[2]);
			node.setDirtyCanvas(true,true);
		}
	}

	return false;
}
```

--------------------------------

### Get Function Parameter Names

Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/files/.._src_litegraph.js.html

Extracts the names of parameters from a JavaScript function. It cleans up comments and default values to return an array of parameter names.

```javascript
LiteGraph.getParameterNames = function(func) {
    return (func + '')
      .replace(/[/][/].*$/mg,'') // strip single-line comments
      .replace(/\s+/g, '') // strip white space
      .replace(/[/][*][^/]*[*][/]/g, '') // strip multi-line comments  /**/
      .split('){', 1)[0].replace(/^[^({]/, '') // extract the parameters
      .replace(/=[^,]+/g, '') // strip any ES6 defaults
      .split(',').filter(Boolean); // split & filter [""]
}
```

--------------------------------

### Render Straight Connections

Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/files/.._src_litegraph.js.html

Renders connections as straight lines with a corner when the link render mode is set to STRAIGHT_LINK. It calculates intermediate points for the corner.

```javascript
else if(this.links_render_mode == LiteGraph.STRAIGHT_LINK)
		{
			ctx.moveTo(a[0], a[1]);
			var start_x = a[0];
			var start_y = a[1];
			var end_x = b[0];
			var end_y = b[1];
			if( start_dir == LiteGraph.RIGHT )
				start_x += 10;
			else
				start_y += 10;
			if( end_dir == LiteGraph.LEFT )
				end_x -= 10;
			else
				end_y -= 10;
			ctx.lineTo(start_x, start_y);
			ctx.lineTo((start_x + end_x)*0.5,start_y);
			ctx.lineTo((start_x + end_x)*0.5,end_y);
			ctx.lineTo(end_x, end_y);
			ctx.lineTo(b[0],b[1]);
		}
```

--------------------------------

### Add a Number Widget with Options

Source: https://github.com/jagenjo/litegraph.js/blob/master/guides/README.md

Define a number widget with specific minimum, maximum, and precision settings. The callback is invoked upon value change.

```javascript
this.addWidget("number","Number", current_value, callback, { min: 0, max: 100, step: 1, precision: 3 } );
```

--------------------------------

### Get File Extension from URL

Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/files/.._src_litegraph.js.html

Extracts the file extension from a given URL, ignoring any query parameters. Returns an empty string if no extension is found.

```javascript
LGraphCanvas.getFileExtension = function (url)
{
	var question = url.indexOf("?");
	if(question != -1)
		url = url.substr(0,question);
	var point = url.lastIndexOf(".");
	if(point == -1)
		return "";
	return url.substr(point+1).toLowerCase();
}
```

--------------------------------

### Get Node Bounding Box - LiteGraph.js

Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/files/.._src_litegraph.js.html

Calculates and returns the bounding box of a node, including its title and any margins. This is used for rendering and collision detection.

```javascript
LGraphNode.prototype.getBounding = function( out )
{
	out = out || new Float32Array(4);
	out[0] = this.pos[0] - 4;
	out[1] = this.pos[1] - LiteGraph.NODE_TITLE_HEIGHT;
	out[2] = this.size[0] + 4;
	out[3] = this.size[1] + LiteGraph.NODE_TITLE_HEIGHT;

	if( this.onBounding )
		this.onBounding( out );
	return out;
}
```

--------------------------------

### Render Output Connection Slots

Source: https://github.com/jagenjo/litegraph.js/blob/master/doc/files/.._src_litegraph.js.html

Renders the output connection slots for a node, including their shape and color. It applies reduced opacity when a connection is being dragged.

```javascript
//output connection slots
		if(this.connecting_node)
			ctx.globalAlpha = 0.4 * editor_alpha;

		ctx.textAlign = horizontal ? "center" : "right";
		ctx.strokeStyle = "black";
		if(node.outputs)
			for(var i = 0; i < node.outputs.length; i++)
			{
				var slot = node.outputs[i];

				var pos = node.getConnectionPos(false,i, slot_pos );
				pos[0] -= node.pos[0];
				pos[1] -= node.pos[1];
				if( max_y < pos[1] + LiteGraph.NODE_SLOT_HEIGHT*0.5)
					max_y = pos[1] + LiteGraph.NODE_SLOT_HEIGHT*0.5;

				ctx.fillStyle = slot.links && slot.links.length ? (slot.color_on || this.default_connection_color.output_on) : (slot.color_off || this.default_connection_color.output_off);
				ctx.beginPath();
				//ctx.rect( node.size[0] - 14,i*14,10,10);

				if (slot.type === LiteGraph.EVENT || slot.shape === LiteGraph.BOX_SHAPE)
				{
					if( horizontal )
						ctx.rect((pos[0] - 5) + 0.5,(pos[1] - 8) + 0.5,10,14);
					else
						ctx.rect((pos[0] - 6) + 0.5,(pos[1] - 5) + 0.5,14,10);
                }
                else if (slot.shape === LiteGraph.ARROW_SHAPE) {
                    ctx.moveTo(pos[0] + 8, pos[1] + 0.5);
                    ctx.lineTo(pos[0] - 4, (pos[1] + 6) + 0.5);
                    ctx.lineTo(pos[0] - 4, (pos[1] - 6) + 0.5);
                    ctx.closePath();
                }
                else {
                    ctx.arc(pos[0], pos[1], 4, 0, Math.PI * 2);
                }

				//trigger
				//if(slot.node_id != null && slot.slot == -1)
				//	ctx.fillStyle = "#F85";

				//if(slot.links != null && slot.links.length)
				ctx.fill();
				ctx.stroke();
			}
```