--- 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 `LGraphCanvas.getCanvasMenuOptions`. The standard way of editing this is to implement the `getCanvasMenuItems` method on your extension: ```javascript app.registerExtension({ name: "MyExtension", getCanvasMenuItems(canvas) { const items = [] items.push(null) // inserts a divider items.push({ content: "The text for the menu", callback: async () => { // do whatever } }) return items } }); ``` ### Node menu When you right click on a node, the menu is similarly generated by `node.getExtraMenuOptions`. The standard way is to implement the `getNodeMenuItems` method on your extension: ```javascript app.registerExtension({ name: "MyExtension", getNodeMenuItems(node) { const items = [] // You can filter by node type if needed if (node.comfyClass === "MyNodeClass") { items.push({ content: "Do something fun", callback: async () => { // fun thing } }) } return items } }); ``` ### Submenus If you want a submenu, use the `submenu` property with an `options` array: ```javascript app.registerExtension({ name: "MyExtension", getCanvasMenuItems(canvas) { const items = [] items.push({ content: "Menu with options", submenu: { options: [ { content: "option 1", callback: (v) => { // do something with v } }, { content: "option 2", callback: (v) => { // do something with v } }, { content: "option 3", callback: (v) => { // do something with v } } ] } }) return items } }); ``` ## 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 **Deprecated:** The API hijacking pattern shown below is deprecated and subject to change at any point in the near future. Use the official [extension hooks](/custom-nodes/js/javascript_hooks) and API event listeners where available. 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 **Deprecated:** The node method hijacking pattern shown below is deprecated and subject to change at any point in the near future. Use the official [extension hooks](/custom-nodes/js/javascript_hooks) where available. `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); } } } ```