Open Context menu in available space on chart

Hi,
I am using org chart and opening context menu on mouse right click on any node but its not opening at exact position where mouse clicked. Can you please let me know if any property to set the positioning of context menu? I am attaching the image for more info.

You can override ContextMenuTool.positionContextMenu to change the position as you please

Start with the default implementation:

myDiagram.toolManager.contextMenuTool.positionContextMenu = function(contextmenu, obj) {
var diagram = this.diagram;
if (diagram === null) return;

var p = diagram.lastInput.documentPoint.copy();
var ttb = contextmenu.measuredBounds;
var viewb = diagram.viewportBounds;
// when touch event – shift towards the left, so it’s not obscured by the finger
if (diagram.lastInput.isTouchEvent) {
p.x -= ttb.width;
}
// if extends too far to the right – shift left
if (p.x + ttb.width > viewb.right) {
p.x -= ttb.width + 5;
}
// but don’t go beyond the left edge of the viewport
if (p.x < viewb.x) {
p.x = viewb.x;
}
// if extends too far down – shift up
if (p.y + ttb.height > viewb.bottom) {
p.y -= ttb.height + 5;
}
// but don’t go beyond the top edge of the viewport
if (p.y < viewb.y) {
p.y = viewb.y;
}
contextmenu.position = p;
};

Thanks for reply…
But I tried the same code this is not working because of var ttb = contextmenu.measuredBounds;
ttb.width and ttb.height is not a numner (NaN). So suggest if other way to find the scroll position of org chart.

Thanks,

How have you defined your context menu?

As HTML…

// This is a dummy context menu for the whole Diagram:
//myDiagram.nodeTemplate.contextMenu = GO(go.Adornment);
myDiagram.groupTemplateMap.get(“CommandSectionGroup”).contextMenu = GO(go.Adornment);
myDiagram.nodeTemplateMap.get(“UnitMember”).contextMenu = GO(go.Adornment);
//myDiagram.contextMenu = GO(go.Adornment);

// This is the actual HTML context menu:
var cxElement = document.getElementById("contextMenu");

// We don't want the div acting as a context menu to have a (browser) context menu!
cxElement.addEventListener("contextmenu", function(e) { e.preventDefault(); return false; }, false);
cxElement.addEventListener("blur", function(e) { cxMenu.stopTool(); }, false);

// Override the ContextMenuTool.showContextMenu and hideContextMenu methods
// in order to modify the HTML appropriately.
var cxTool = myDiagram.toolManager.contextMenuTool;

// This is the override of ContextMenuTool.showContextMenu:
// This does not not need to call the base method.
cxTool.showContextMenu = function (contextmenu, obj) {
    //;
    var diagram = this.diagram;
    if (diagram === null) return;

    // Hide any other existing context menu
    if (contextmenu !== this.currentContextMenu) {
        this.hideContextMenu();
    }

    //disable enable code disable
    var cmdAction = diagram.commandHandler;

    enableDisableExpandCollapseLink(diagram);
    
    
    if (!diagram.selection.first().data.isGroup) {
        $(".edit-unit").removeClass('disable');
        $('.delete-unit').removeClass('disable');
    }
    else {
        $(".edit-unit").addClass('disable');
        $('.delete-unit').addClass('disable');
    }


    // Show only the relevant buttons given the current state.
    ////////////var cmd = diagram.commandHandler;
    ////////////document.getElementById("cut").style.display = cmd.canCutSelection() ? "block" : "none";
    ////////////document.getElementById("copy").style.display = cmd.canCopySelection() ? "block" : "none";
    ////////////document.getElementById("paste").style.display = cmd.canPasteSelection() ? "block" : "none";
    ////////////document.getElementById("delete").style.display = cmd.canDeleteSelection() ? "block" : "none";
    ////////////document.getElementById("color").style.display = obj !== null ? "block" : "none";

    // Now show the whole context menu element
    cxElement.style.display = "block";

    // we don't bother overriding positionContextMenu, we just do it here:       
    var mousePt = getCursorPosition(diagram.lastInput.viewPoint);        
    cxElement.style.left = mousePt.left + "px";
    cxElement.style.top = mousePt.top + "px";

    //var mousePt = diagram.lastInput.viewPoint;
    //cxElement.style.left = $('#myDiagram').position().left + mousePt.x + "px";
    //cxElement.style.top = $('#myDiagram').position().top + mousePt.y + "px";     
    // Remember that there is now a context menu showing
    this.currentContextMenu = contextmenu;
}

// This is the corresponding override of ContextMenuTool.hideContextMenu:
// This does not not need to call the base method.
cxTool.hideContextMenu = function() {
    if (this.currentContextMenu === null) return;
    cxElement.style.display = "none";
    this.currentContextMenu = null;
}

Oh sorry, I thought your context menu was an Adornment, not HTML.

If the context menu is defined as HTML, then GoJS cannot account for its position, you have to do it yourself based on your own calculations.

The part you copied from customContextMenu.html would need to be updated:

    // we don't bother overriding positionContextMenu, we just do it here:       
    var mousePt = getCursorPosition(diagram.lastInput.viewPoint);        
    cxElement.style.left = mousePt.left + "px";
    cxElement.style.top = mousePt.top + "px";

to also reflect the size of the context menu and its location on the screen. We don’t have any examples of that unfortunately, and positioning HTML elements on a page is outside the scope of GoJS.