# Source: https://docs.comfy.org/custom-nodes/js/javascript_examples.md

> ## Documentation Index
> Fetch the complete documentation index at: https://docs.comfy.org/llms.txt
> Use this file to discover all available pages before exploring further.

# 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  theme={null}
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  theme={null}
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  theme={null}
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  theme={null}
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  theme={null}
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

<Note>
  **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.
</Note>

A simple example of hijacking the api:

```Javascript  theme={null}
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

<Note>
  **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.
</Note>

`node` has a mouseDown method you can hijack.
This time we're careful to pass on any return value.

```javascript  theme={null}
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);
        }        
    }
}
```