--- title: "Annotated Examples" --- A growing collection of fragments of example code... ## Right click menus ### Background menu The main background menu (right-click on the canvas) is generated by a call to `LGraph.getCanvasMenuOptions`. One way to add your own menu options is to hijack this call: ```Javascript /* in setup() */ const original_getCanvasMenuOptions = LGraphCanvas.prototype.getCanvasMenuOptions; LGraphCanvas.prototype.getCanvasMenuOptions = function () { // get the basic options const options = original_getCanvasMenuOptions.apply(this, arguments); options.push(null); // inserts a divider options.push({ content: "The text for the menu", callback: async () => { // do whatever } }) return options; } ``` ### Node menu When you right click on a node, the menu is similarly generated by `node.getExtraMenuOptions`. But instead of returning an options object, this one gets it passed in... ```javascript /* in beforeRegisterNodeDef() */ if (nodeType?.comfyClass=="MyNodeClass") { const original_getExtraMenuOptions = nodeType.prototype.getExtraMenuOptions; nodeType.prototype.getExtraMenuOptions = function(_, options) { original_getExtraMenuOptions?.apply(this, arguments); options.push({ content: "Do something fun", callback: async () => { // fun thing } }) } } ``` ### Submenus If you want a submenu, provide a callback which uses `LiteGraph.ContextMenu` to create it: ```javascript function make_submenu(value, options, e, menu, node) { const submenu = new LiteGraph.ContextMenu( ["option 1", "option 2", "option 3"], { event: e, callback: function (v) { // do something with v (=="option x") }, parentMenu: menu, node:node } ) } /* ... */ options.push( { content: "Menu with options", has_submenu: true, callback: make_submenu, } ) ``` ## Capture UI events This works just like you'd expect - find the UI element in the DOM and add an eventListener. `setup()` is a good place to do this, since the page has fully loaded. For instance, to detect a click on the 'Queue' button: ```Javascript function queue_button_pressed() { console.log("Queue button was pressed!") } document.getElementById("queue-button").addEventListener("click", queue_button_pressed); ``` ## Detect when a workflow starts This is one of many `api` events: ```javascript import { api } from "../../scripts/api.js"; /* in setup() */ function on_execution_start() { /* do whatever */ } api.addEventListener("execution_start", on_execution_start); ``` ## Detect an interrupted workflow A simple example of hijacking the api: ```Javascript import { api } from "../../scripts/api.js"; /* in setup() */ const original_api_interrupt = api.interrupt; api.interrupt = function () { /* Do something before the original method is called */ original_api_interrupt.apply(this, arguments); /* Or after */ } ``` ## Catch clicks on your node `node` has a mouseDown method you can hijack. This time we're careful to pass on any return value. ```javascript async nodeCreated(node) { if (node?.comfyClass === "My Node Name") { const original_onMouseDown = node.onMouseDown; node.onMouseDown = function( e, pos, canvas ) { alert("ouch!"); return original_onMouseDown?.apply(this, arguments); } } } ```