Contextmenu location

The sooner the better is the key for today :wink:

in master for testing

Wasn't the Sunday the day of being in relax mode🙂

Did you get any free time to look at dceejay's addition to git master @BartButenaers

I think we have a misunderstanding. I thought that you were going to whether the pimped button worked correctly together with your contextmenu. If you want, I can try your flow with Dave's fix. But I'm afraid you will have to wait a bit longer, because it is even more busy at home now with schools closed...

Apologies @BartButenaers @dceejay
It usually takes me a few minutes or hours to fully comprehend how things work around here, but it's unfortunately taken me 2 weeks to grasp this :shushing_face:
I think that the plan is to grab the coordinates from the button node, and feed those into the contextmenu node by way of Message based fields.
OK I get it!!!

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.


Clicking around the icon -

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

Clicking the icon -

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

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.

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


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

Thank you


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.


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).

1 Like

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




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.


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


Hi Daniel,
I see here 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...

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.

Nice catch! I have created a new issue 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!

@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.


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

    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;

        // Get the mouse coordinates (with origin at left top of the SVG drawing)
        let evtpos = pointerEventToXY(evt);
            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;

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

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?).

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.

1 Like