Context Menu position

Hi, @BartButenaers
I don't know if this is in my setup but if I open a context menu to close to the bottom of the canvas and it contains a number of entries the menu goes over the edge.

If the menu is opened to far right of the canvas the items switch to the other side but leaves a small gap between them. and it seem to increase with more sub-menus. This can be an issue if auto close is active and you move to slowly, the menu collapses beforw selection.


Hi Daniel (@greenembrace),

Unfortunately this part of my node has been developed by someone else (@Steve-Mcl). It uses a third party library (JS and CSS), which has been customized for our node. But Steve has not much time lately, so I'm afraid this issue won't be solved until he ever gets back in the community... Or perhaps if somebody else wants to have a look at it of course. But I won't be able to solve this on my own. Sorry!


Hi, the collision detection isn't the greatest - could you add it as an issue to the GitHub repo please? It will get looked at when I get time - perhaps sooner than later due to our friendly neighbourhood coronavirus :+1:

1 Like

Thanks guys, @BartButenaers @Steve-Mcl I can live with it, I was just concerned for the fantastic node. Happy to put in an issue, when I rise tomorrow hopefully.

Slightly O/T... but is there anyway to keep open the 2nd level menu when using a mobile device.
Currently, it's easy to select items on the first level, but when expanded to the second level it collapses immediately, making it difficult to select a menu item.


Hey @Paul-Reed,

We have an auto hide feature on the contextmenu.
That feature has been expanded a few weeks ago, because some users wanted to have more control of it:


So I 'think' that navigating with the mouse from the first level contextmenu to the second level context menu, is considered as leaving the contextmenu (so the contextmenu will be hidden...). We will need to have a look at that also. Have put it on my todo list ...

I have the auto-hide set to 2 seconds, but the menu hides immediately a selection is made on the first level menu, so you don't even get access to the second level menu at all, not even for 2 seconds.

@Paul-Reed & @greenembrace, would you be willing to test the modifications I made?

To install, you will need to install via github...

  1. open a cmd/terminal
  2. cd to your node-red folder
  3. npm install bartbutenaers/node-red-contrib-ui-contextmenu
  4. Restart your node-red
  • I think I've solved the mobile menu closing issue
  • I have (for now) tweaked the menu positioning (might be an improvement / might not)

@BartButenaers I think we might have to manually calculate the left position for each sub menu (if placement is not possible on the right) because the .cm_container.cm_border_right > ul ul css class is too broad for differing width sub menus.

Cheers, Steve.


Great!! now able to select the second level menu on a mobile device.
Nice work @Steve-Mcl & @BartButenaers :+1:
(PS - it works much better than it appears in the gif)


I'll link this thread to the other 'Context Menu Location' thread for info -

All credits for this fix go to @Steve-Mcl. Nice job and fast.
Thanks for your assistance Steve !!

Gentlemen (@Steve-Mcl, @Paul-Reed),
Is it ok to publish Steve's changes to npm?
Because my node administration is becoming quite a mess :wink:

Still working very well here :blush:
However I don't think @dceejay has updated the dashboard with the 'button' changes just yet, so if you have added the button trick to your node's readme, it won't work just yet.

1 Like

Nope not done yet, but it is written down in my todo list for later :wink:


I'll probably get next dashboard release out next week - just need to check some other things first.


version 1.0.11 (which contains your fix) is available on NPM:


BTW now I see that I should have added the button example. Damn. Forgotten ...

1 Like

@greenembrace - i have updated a special branch with new layout calculations.

If you are willing to test, please install from github like this...

  1. CD to node red folder (usually ~/.node-red or %userprofile%\.node-red)
  2. uninstall npm version
    1. npm u node-red-contrib-ui-contextmenu
  3. install github version
    1. npm install bartbutenaers/node-red-contrib-ui-contextmenu#new_layout_calcs
  4. restart node-red

@BartButenaers - could you test this branch please.

1 Like

Hey Steve,
Will test it tonight. Wow that looks pretty cool!!!! :clap:

I have done a test with this flow:

[{"id":"689bbda1.e3a7d4","type":"ui_svg_graphics","z":"11289790.c89848","group":"54828f58.3ac8e","order":1,"width":"14","height":"10","svgString":"<svg xmlns=\"\" xmlns:svg=\"\" xmlns:xlink=\"\" preserveAspectRatio=\"none\" x=\"0\" y=\"0\" viewBox=\"0 0 900 710\" width=\"100%\" height=\"100%\">\n  <rect id=\"svgEditorBackground\" x=\"0\" y=\"0\" width=\"900\" height=\"710\" style=\"fill:none;stroke:none;\" />\n  <image width=\"889\" height=\"703\" id=\"background\" xlink:href=\"\" />\n  <circle id=\"mycircle\" cx=\"182.901\" cy=\"91.4841\" style=\"fill:rosybrown;stroke:black;stroke-width:1px;\" r=\"48\" /></svg>","clickableShapes":[{"targetId":"#mycircle","action":"click","payload":"camera_living","payloadType":"str","topic":"camera_living"}],"smilAnimations":[],"bindings":[{"selector":"#banner","bindSource":"payload.title","bindType":"text","attribute":""},{"selector":"#camera_living","bindSource":"payload.position.x","bindType":"attr","attribute":"x"},{"selector":"#camera_living","bindSource":"","bindType":"attr","attribute":"fill"}],"showCoordinates":false,"autoFormatAfterEdit":false,"selectorAsElementId":true,"outputField":"","editorUrl":"","directory":"","panEnabled":false,"zoomEnabled":false,"controlIconsEnabled":false,"dblClickZoomEnabled":false,"mouseWheelZoomEnabled":false,"name":"","x":380,"y":220,"wires":[["e8076981.99f448"]]},{"id":"405c3d89.b0be34","type":"ui_context_menu","z":"11289790.c89848","group":"54828f58.3ac8e","order":5,"width":0,"height":-1,"fontSize":16,"position":"msg","outputField":"payload","xCoordinate":50,"yCoordinate":50,"menu":"msg","menuItems":[],"colors":"native","textColor":"#000000","backgroundColor":"#ffffff","borderColor":"#626262","intervalLength":"0","intervalUnit":"secs","startTimerAtOpen":false,"startTimerAtLeave":true,"stopTimerAtEnter":true,"name":"","x":820,"y":220,"wires":[[]]},{"id":"e8076981.99f448","type":"change","z":"11289790.c89848","name":"","rules":[{"t":"set","p":"menu","pt":"msg","to":"[{\"text\":\"Options\",\"icon\":\"fa-list\",\"sub\":[{\"text\":\"Edit\",\"icon\":\"fa-edit\",\"topic\":\"edit\",\"payload\":[1,2,3,4,5],\"payloadType\":\"JSON\",\"outputField\":\"editArray\"},{\"text\":\"Cut\",\"icon\":\"fa-cut\",\"enabled\":true,\"topic\":\"cut\",\"payload\":\"true\",\"payloadType\":\"bool\"},{\"text\":\"Options\",\"icon\":\"fa-list\",\"sub\":[{\"text\":\"Edit\",\"icon\":\"fa-edit\",\"topic\":\"edit\",\"payload\":[1,2,3,4,5],\"payloadType\":\"JSON\",\"outputField\":\"editArray\"},{\"text\":\"Cut\",\"icon\":\"fa-cut\",\"enabled\":true,\"topic\":\"cut\",\"payload\":\"true\",\"payloadType\":\"bool\"},{\"text\":\"Options\",\"icon\":\"fa-list\",\"sub\":[{\"text\":\"Edit\",\"icon\":\"fa-edit\",\"topic\":\"edit\",\"payload\":[1,2,3,4,5],\"payloadType\":\"JSON\",\"outputField\":\"editArray\"},{\"text\":\"Cut\",\"icon\":\"fa-cut\",\"enabled\":true,\"topic\":\"cut\",\"payload\":\"true\",\"payloadType\":\"bool\"},{\"text\":\"Options\",\"icon\":\"fa-list\",\"sub\":[{\"text\":\"Edit\",\"icon\":\"fa-edit\",\"topic\":\"edit\",\"payload\":[1,2,3,4,5],\"payloadType\":\"JSON\",\"outputField\":\"editArray\"},{\"text\":\"Cut\",\"icon\":\"fa-cut\",\"enabled\":true,\"topic\":\"cut\",\"payload\":\"true\",\"payloadType\":\"bool\"},{\"text\":\"Options\",\"icon\":\"fa-list\",\"sub\":[{\"text\":\"Edit\",\"icon\":\"fa-edit\",\"topic\":\"edit\",\"payload\":[1,2,3,4,5],\"payloadType\":\"JSON\",\"outputField\":\"editArray\"},{\"text\":\"Cut\",\"icon\":\"fa-cut\",\"enabled\":true,\"topic\":\"cut\",\"payload\":\"true\",\"payloadType\":\"bool\"},{\"text\":\"Options\",\"icon\":\"fa-list\",\"sub\":[{\"text\":\"Edit\",\"icon\":\"fa-edit\",\"topic\":\"edit\",\"payload\":[1,2,3,4,5],\"payloadType\":\"JSON\",\"outputField\":\"editArray\"},{\"text\":\"Cut\",\"icon\":\"fa-cut\",\"enabled\":true,\"topic\":\"cut\",\"payload\":\"true\",\"payloadType\":\"bool\"},{\"text\":\"Cut\",\"icon\":\"fa-cut\",\"enabled\":true,\"topic\":\"cut\",\"payload\":\"true\",\"payloadType\":\"bool\"}]}]}]}]}]}]}]","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":600,"y":220,"wires":[["405c3d89.b0be34","af022471.bc74a8"]]},{"id":"54828f58.3ac8e","type":"ui_group","z":"","name":"Floorplan test","tab":"ecbf4f1e.06ad9","order":1,"disp":true,"width":"14","collapse":false},{"id":"ecbf4f1e.06ad9","type":"ui_tab","z":"","name":"SVG","icon":"dashboard","disabled":false,"hidden":false}]

And to me that seems to be working fine:

Cool. I'll wait feedback from @greenembrace before merging.