# Contextmenu location

**URL:** <https://discourse.nodered.org/t/contextmenu-location/22780>\
**Category:** Developing Nodes\
**Created:** [7 March 2020 22:46 UTC](https://discourse.nodered.org/t/contextmenu-location/22780 "2020-03-07T22:46:23Z")\
**Posts on this page:** 20\
**Page:** 3

<div class="post-metadata">

**Author:** ![Paul-Reed](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/paul-reed/32/66906_2.png) [@Paul-Reed](https://discourse.nodered.org/u/Paul-Reed)\
**Post date:** [27 March 2020 21:17 UTC](https://discourse.nodered.org/t/contextmenu-location/22780/41 "2020-03-27T21:17:38Z")

</div>

> [@dceejay](#):
>
> Yes I have a patch for this

This is working OK aligning the menu to the top right of the box, but I've found a minor issue when using an icon in the button node.  
If I click anywhere in the box (other than the icon), the position is reported correctly, if however I click the icon itself, the coordinates reported change and are incorrect.

![men](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/a/e/aee8b33a2d6e790c11c8b5325fb680e4c2628e2d.gif)

Clicking around the icon -

```auto
bbox: array[4]
0: 313
1: 179
2: 372
3: 120

```

Clicking the icon -

```auto
bbox: array[4]
0: 331
1: 195
2: 390
3: 136

```

---

<div class="post-metadata">

**Author:** ![hotNipi](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/hotnipi/32/383_2.png) [@hotNipi](https://discourse.nodered.org/u/hotNipi)\
**Post date:** [27 March 2020 21:46 UTC](https://discourse.nodered.org/t/contextmenu-location/22780/42 "2020-03-27T21:46:11Z")

</div>

The click event is tied to clicked element. The box can be measured from any known part of component. The overall question is - what is the meaningfull box the component should provide. There is one and straight rule as for button it may be whole button but for more complex elements there is many possibilities. I know for state-trail the box has no meaning at all. So it is pretty  
hard to lay out rules that way.

---

<div class="post-metadata">

**Author:** ![dceejay](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dceejay/32/38_2.png) [@dceejay](https://discourse.nodered.org/u/dceejay)\
**Post date:** [28 March 2020 15:42 UTC](https://discourse.nodered.org/t/contextmenu-location/22780/43 "2020-03-28T15:42:27Z")

</div>

@Paul-Reed I've pushed a better fix to master - give that a whirl.

---

<div class="post-metadata">

**Author:** ![Paul-Reed](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/paul-reed/32/66906_2.png) [@Paul-Reed](https://discourse.nodered.org/u/Paul-Reed)\
**Post date:** [28 March 2020 15:54 UTC](https://discourse.nodered.org/t/contextmenu-location/22780/44 "2020-03-28T15:54:30Z")

</div>

Nice! works really well now, and the button is spitting out the same coordinates wherever the user clicks within the bounding box.

Thank you

![menutest](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/8/e/8e0a2713a16063346e5f50525f460074ae381012.gif)

---

<div class="post-metadata">

**Author:** ![Paul-Reed](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/paul-reed/32/66906_2.png) [@Paul-Reed](https://discourse.nodered.org/u/Paul-Reed)\
**Post date:** [28 March 2020 16:13 UTC](https://discourse.nodered.org/t/contextmenu-location/22780/45 "2020-03-28T16:13:46Z")

</div>

In fact, this is @BartButenaers & @Steve-Mcl's contextmenu node, as used in my dashboard.  
The dashboard size is deigned for my phone in landscape, and the menu works great there too!  
The changes made by @dceejay have made it now that the menu popup always appears in the same location, regardless of the browser.  
Also, really liking @hotNipi's artless-gauges, their simplicity seems to make data easier to absorb.

 ![site2](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/2/4/2448d55e29587213a10eb65aa7c513ae33cecbc4.gif)

---

<div class="post-metadata">

**Author:** ![BartButenaers](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bartbutenaers/32/10476_2.png) [@BartButenaers](https://discourse.nodered.org/u/BartButenaers)\
**Post date:** [28 March 2020 18:29 UTC](https://discourse.nodered.org/t/contextmenu-location/22780/46 "2020-03-28T18:29:47Z")

</div>

Hey @dceejay, @Paul-Reed,  
Nice work! Thank you both for the assistance!  
I really should add a simple example to the contextmenu node's readme page, to show the cooperation with the button widget (once the feature is on NPM).

---

<div class="post-metadata">

**Author:** ![Paul-Reed](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/paul-reed/32/66906_2.png) [@Paul-Reed](https://discourse.nodered.org/u/Paul-Reed)\
**Post date:** [28 March 2020 20:00 UTC](https://discourse.nodered.org/t/contextmenu-location/22780/47 "2020-03-28T20:00:10Z")

</div>

Just tweaking the position a little makes the menu appear in a more natural position relative to the button icon;

![pos](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/f/8/f829267ebe98f80a68efbe492b5e42d2f3e41260.jpeg)

![flow](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/3/7/374a3035cf75617b280580d5f9a3bfc7a863c926.jpeg)

![json](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/2/a/2a1dc5a065b4c92984045fcd65d18900a900ffcf.jpeg)

PS - As I use a common menu across all pages, I load the 'message based' menu from context - so I only have to edit it once to make global menu changes.

---

<div class="post-metadata">

**Author:** ![greenembrace](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/greenembrace/32/42414_2.png) [@greenembrace](https://discourse.nodered.org/u/greenembrace)\
**Post date:** [29 April 2020 23:36 UTC](https://discourse.nodered.org/t/contextmenu-location/22780/48 "2020-04-29T23:36:05Z")

</div>

I may be reading this incorrectly, but the 'touchstart' event does not return msg.position or msg.coordinates.

cheers

---

<div class="post-metadata">

**Author:** ![BartButenaers](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bartbutenaers/32/10476_2.png) [@BartButenaers](https://discourse.nodered.org/u/BartButenaers)\
**Post date:** [30 April 2020 16:48 UTC](https://discourse.nodered.org/t/contextmenu-location/22780/49 "2020-04-30T16:48:33Z")

</div>

> [@greenembrace](#):
>
> the 'touchstart' event does not return

Hi Daniel,  
I see [here](https://github.com/node-red/node-red-dashboard/blob/df8c39dfc9cfdd099005ca7b5d2e8ac9c5af27cb/src/components/ui-component/ui-component-ctrl.js) that @dceejay has added it to the buttonClick event. But don't see any other button related event (e.g. touchstart) there. So expected the same behaviour...  
Bart

---

<div class="post-metadata">

**Author:** ![greenembrace](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/greenembrace/32/42414_2.png) [@greenembrace](https://discourse.nodered.org/u/greenembrace)\
**Post date:** [1 May 2020 02:37 UTC](https://discourse.nodered.org/t/contextmenu-location/22780/50 "2020-05-01T02:37:16Z")

</div>

Hi Bart,  
Specifically I was interested in your SVG nodes output and should have said such in the message, but as it related to the 'contextmenu' I put it here. I don't know where to place the menu. I could just put it in the top corner but on a 7in screen that annoying.

---

<div class="post-metadata">

**Author:** ![BartButenaers](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bartbutenaers/32/10476_2.png) [@BartButenaers](https://discourse.nodered.org/u/BartButenaers)\
**Post date:** [1 May 2020 06:33 UTC](https://discourse.nodered.org/t/contextmenu-location/22780/51 "2020-05-01T06:33:49Z")

</div>

> [@greenembrace](#):
>
> Specifically I was interested in your SVG nodes

Nice catch! I have created a new [issue](https://github.com/bartbutenaers/node-red-contrib-ui-svg/issues/59) for the SVG node. Will need to refactor the coordinate related fields in the output message anyway in the 2.0.0 release, to use the same fields as the other UI nodes (as described above in this discussion). Will keep you updated!

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [1 May 2020 09:18 UTC](https://discourse.nodered.org/t/contextmenu-location/22780/52 "2020-05-01T09:18:14Z")

</div>

@greenembrace for now, is there any reason you are using `touchstart` over `click`? Click should work on a touch screen & does contain coordintated.

@BartButenaers we need to handle this differently.

the touch events present their pageX and pageY coordinates in a different property to click.

e.g...

```auto
//touch event
pt.x = evt.originalEvent.touches[0].pageX;
pt.y = evt.originalEvent.touches[0].pageY;

//click event
pt.x = evt.pageX;
pt.y = evt.pageY;

```

So we can fix touch events like this...

```auto
    initController: function($scope, events) {
        // Remark: all client-side functions should be added here!  
        // If added above, it will be server-side functions which are not available at the client-side ...
        

        // ADD THIS FUNCTION INSIDE initController....
        //helper function to get event coordinates
        function pointerEventToXY(e){
            if(e.type == 'touchstart' || e.type == 'touchmove' || e.type == 'touchend' || e.type == 'touchcancel'){
                var touches = e.touches || e.originalEvent && e.originalEvent.touches.touches;
                if(touches && touches.length){
                    var touch = touches[0] || changedTouches[0];
                    return {
                        x : touch.pageX,
                        y : touch.pageY
                    }
                }
            } else if (e.type == 'click' || e.type == 'mousedown' || e.type == 'mouseup' || e.type == 'mousemove' || e.type == 'mouseover'|| e.type=='mouseout' || e.type=='mouseenter' || e.type=='mouseleave') {
                return {
                    x : e.pageX,
                    y : e.pageY
                }
            }
            return null;
        };

        ...
        ...
        ...
        //CHANGE THE BELOW AS FOLLOWS...
        // Get the mouse coordinates (with origin at left top of the SVG drawing)
        let evtpos = pointerEventToXY(evt);
        if(evtpos){
            var pt = $scope.svg.createSVGPoint();
            pt.x = evtpos.x;
            pt.y = evtpos.y;
            pt = pt.matrixTransform($scope.svg.getScreenCTM().inverse());
            //relative position on svg
            msg.coordinates = {
                x: pt.x,
                y: pt.y
            }
            //absolute position on page - usefull for sending to popup menu
            msg.position = evtpos;
        }

```

---

<div class="post-metadata">

**Author:** ![BartButenaers](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bartbutenaers/32/10476_2.png) [@BartButenaers](https://discourse.nodered.org/u/BartButenaers)\
**Post date:** [1 May 2020 09:37 UTC](https://discourse.nodered.org/t/contextmenu-location/22780/53 "2020-05-01T09:37:52Z")

</div>

> [@Steve-Mcl](#):
>
> Click should work on a touch screen & does contain coordintated.

Steve, tried that this morning but (if I'm not mistaken) it didn't work on my Android phone. The touchstart worked fine.

> [@Steve-Mcl](#):
>
> So we can fix touch events like this...

Thanks for having a look at this!! I'm not at my pc at the moment, but we perhaps need to look at the fields that @dceejay has used for his button (and use the same + also send old fields for legacy flows?).

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [1 May 2020 09:51 UTC](https://discourse.nodered.org/t/contextmenu-location/22780/54 "2020-05-01T09:51:19Z")

</div>

Don't need to support anything legacy as far as I can see Bart. It just didn't work for a touchscreen when using touchstart. TBH, most users would instinctively choose click.

And even if they did choose touch events, the odds are even smaller they would be using the context menu and odds reduce even further that they're using dynamic position.

Lastly, the worst that can happen? The context menus appear in the correct location.

Ps, I tried the above code & it works for me.

---

<div class="post-metadata">

**Author:** ![BartButenaers](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bartbutenaers/32/10476_2.png) [@BartButenaers](https://discourse.nodered.org/u/BartButenaers)\
**Post date:** [1 May 2020 10:05 UTC](https://discourse.nodered.org/t/contextmenu-location/22780/55 "2020-05-01T10:05:25Z")

</div>

> [@Steve-Mcl](#):
>
> Don't need to support anything legacy as far as I can see Bart

Seems I had posted an incorrect link. This is the [issue](https://github.com/bartbutenaers/node-red-contrib-ui-svg/issues/59). For the "click" event we currently (npm version) send this output:

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/9/b/9bf26c8b8ea84a309977d8ccd44383f9f4fda817.png)

But the dashboard button:  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/d/d/dd20b313dee5bb54901aafc4a5d8f4706e29ea56.png)

Sends this when clicked:

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/a/4/a425ef7168fe13a0988fc438bb882124b6ed063d.png)

Don't know if @hotNipi has also used the same convention meanwhile for his UI node(s)? But if we would use rename our fields, then we break existing flows.  
Of course there is no issue when we add the bounding box, since that is a new output message field (which we can get via `document.getElementById("myPath").getBBox();` ).

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [1 May 2020 10:14 UTC](https://discourse.nodered.org/t/contextmenu-location/22780/56 "2020-05-01T10:14:11Z")

</div>

We could just add those to the click type events and if present in the context menu, use them.

No need for any legacy flags as far as I can see Bart.

---

<div class="post-metadata">

**Author:** ![hotNipi](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/hotnipi/32/383_2.png) [@hotNipi](https://discourse.nodered.org/u/hotNipi)\
**Post date:** [1 May 2020 13:37 UTC](https://discourse.nodered.org/t/contextmenu-location/22780/58 "2020-05-01T13:37:05Z")

</div>

I haven't changed anything cos there wasn't clear agreement for unification.  
State-trail still uses this:  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/5/c/5c174e280a634cdf3ff5dd50b71af862dcc51934.png)  
But I will change if needed even if it break some flows. It is not that drastic.

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [1 May 2020 13:51 UTC](https://discourse.nodered.org/t/contextmenu-location/22780/59 "2020-05-01T13:51:21Z")

</div>

Perhaps we should align on including an `event` object in the `msg` with `pageX` and `pageY` at minimum?

> [`MouseEvent.pageX`](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/pageX) Read only
> 
> The X coordinate of the mouse pointer relative to the whole document.
> 
> [`MouseEvent.pageY`](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/pageY) Read only
> 
> The Y coordinate of the mouse pointer relative to the whole document.

then if we have other coordinates, try to stick to mozilla standards (where it makes sense)

e.g. screenX, screenY, clientX, clientY, etc (and touch events)

---

<div class="post-metadata">

**Author:** ![hotNipi](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/hotnipi/32/383_2.png) [@hotNipi](https://discourse.nodered.org/u/hotNipi)\
**Post date:** [1 May 2020 15:04 UTC](https://discourse.nodered.org/t/contextmenu-location/22780/60 "2020-05-01T15:04:34Z")

</div>

So this will be the state-trail output

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/4/c/4c4286ab20e46818da2d9d89fa85a04dc1ccb29a.png)

---

<div class="post-metadata">

**Author:** ![dceejay](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dceejay/32/38_2.png) [@dceejay](https://discourse.nodered.org/u/dceejay)\
**Post date:** [1 May 2020 15:08 UTC](https://discourse.nodered.org/t/contextmenu-location/22780/61 "2020-05-01T15:08:11Z")

</div>

as per above the button sends this

> [@BartButenaers](#):
>
> ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/a/4/a425ef7168fe13a0988fc438bb882124b6ed063d.png)

[Previous page](https://discourse.nodered.org/t/contextmenu-location/22780.md?page=2)

[Next page](https://discourse.nodered.org/t/contextmenu-location/22780.md?page=4)
