5

i am using the ARCGIS Javascript API and trying to override the default right click behavior of the vertex points of a shape.

in ESRI's help it does list the onVertexClick event however from here it seems there is no way to determine if this is a right or left click event so i cannot override just the rightclick. https://developers.arcgis.com/javascript/jsapi/edit.html

I am trying to set the right click behavour to just delete the current node/vertex instead of showing a menu with the option Delete.

EDIT Here is the current event that exists within the ARCGIS api.

this.eventsList.push(dojo.connect(this._editToolbar, 'onVertexClick', $.proxy(this.addCustomVertexClickEvent, this)));

this event is already in the api however it does not return any way for me to determine left/right click.

your comment "listen for the click event then test the button attribute of the MouseEvent object" would work however i cant actually add a click event to the vertex points directly as these are inside the ARCGIS api code.

penance
  • 91
  • 6
  • possible duplicate of [Is right click a Javascript event?](http://stackoverflow.com/questions/2405771/is-right-click-a-javascript-event) – Chris Pickford Sep 17 '14 at 14:41
  • Please post some relevant example code including markup. Essentially what you need to do is listen for the click event then test the button attribute of the MouseEvent object. – Chris Pickford Sep 17 '14 at 14:42

3 Answers3

2

For anyone else who is looking for a way to do this without hacking around. You can listen to "contextmenu" (right click) events on the body, set a flag in the "contextmenu" handler to let the application know the current state. Simulate a click event to the "vertex handle" with a "mousedown", "mouseup" combination. In the "vertex-click" handler check for the right click flag set in the "contextmenu" handler

var editToolbar = new Edit(map, options);
var rightClick;

$('body').on('contextmenu', function(e) {
  var target = e.target;
  if(target.tagName === 'circle') {
    // We only care about this event if it targeted a vertex
    // which is visualized with an SVG circle element
    // Set flag for right click
    rightClick = true;
    // Simulate click on vertex to allow esri vertex-click
    // to fill in the data for us
    var mouseDownEvt = new MouseEvent('mousedown', e.originalEvent);
    target.dispatchEvent(mouseDownEvt);
    var mouseUpEvt = new MouseEvent('mouseup', e.originalEvent);
    target.dispatchEvent(mouseUpEvt);
    // Since this event will be handled by us lets prevent default
    // and stop propagation so the browser context menu doesnt appear
    e.preventDefault();
    e.stopPropagation();
  }
});

editToolbar.on('vertex-click', function(e) {
  if(rightClick) {
    // Handle the right click on a vertex
    rightClick = null;
  }
});
  • This nearly worked for me but in my version js API and chrome it didn't quite work. The context menu event was not firing, I suspect esri is preventing propagation. So I had to set new EditToolbar(this.map, {allowDeleteVertices: false});. Also I had to add a 300ms timeout because the 'vertex-click' fired before the contextmenu. For delete I will re-build the menu – David Wilton Aug 20 '20 at 01:29
1

after hearing back from ESRI it seems they do not provide this detail in their API so this is not possible yet.

penance
  • 91
  • 6
0

I ended up doing this differently. I wanted to add a UI so the user could enter the XY of the point

enter image description here

    // setup to allow editing
    this.editToolbar = new EditToolbar(this.map, { allowDeleteVertices: false });
    const rcMenuForGraphics = new RightClickVertexContextMenu();
    const menu =  rcMenuForGraphics.createMenu();
    // bind to the map graphics as this is where the vertex editor is
    this.map.graphics.on("mouse-over", (evt)=> {
        // bind to the graphic underneath the mouse cursor
        menu.bindDomNode(evt.graphic.getDojoShape().getNode());
      });

      this.map.graphics.on("mouse-out", (evt)=> {
        menu.unBindDomNode(evt.graphic.getDojoShape().getNode());
    });

    this.editToolbar.on("vertex-click", (evt2) => {
        rcMenuForGraphics.setCurrentTarget(evt2);
        // evt2.vertexinfo.graphic.geometry.setX(evt2.vertexinfo.graphic.geometry.x - 1000);
    })

    // when the graphics layer is clicked start editing
    gl.on("click", (evt: any) => {
        this.map.setInfoWindowOnClick(false);
        // tslint:disable-next-line: no-bitwise
        const t: any = EditToolbar.MOVE | EditToolbar.EDIT_VERTICES;
        this.editToolbar.deactivate();
        this.editToolbar.activate(t, evt.graphic);
    })

The code for the menu uses esri's vertex editor to grab the point, change its XY and then manually call the events to refresh the geometry. Only tested with polygon

import Menu = require("dijit/Menu");
import MenuItem = require("dijit/MenuItem");
import Graphic = require("esri/graphic");
import Edit = require("esri/toolbars/edit");
import Point = require("esri/geometry/Point");

class RightClickVertexContextMenu {

  private curentTarget: { graphic: Graphic; vertexinfo: any; target: Edit; };
  public createMenu() {
    const menuForGraphics = new Menu({});

    menuForGraphics.addChild(new MenuItem({
        label: "Edit",
        onClick: () => {
            // this is a bit hooky. We grab the verx mover, change the x/y and then call the _moveStopHandler
            console.log(this.curentTarget.vertexinfo);
            const e: any =  this.curentTarget.target;
            const mover = e._vertexEditor._findMover(this.curentTarget.vertexinfo.graphic);
            const g: Graphic = mover.graphic;
            // add in a UI here to allow the user to set the new value. This just shifts the point to the left
            g.setGeometry(new Point(mover.point.x - 1000, mover.point.y ))
            e._vertexEditor._moveStopHandler(mover, {dx: 15});
            this.curentTarget.target.refresh();
        }
    }));

    menuForGraphics.addChild(new MenuItem({
        label: "Delete",
        onClick: () => {
            // call the vertex delete handler
            const ct: any = this.curentTarget.target;
            ct._vertexEditor._deleteHandler(this.curentTarget.graphic)
        }
    }));

    return menuForGraphics;
}

public setCurrentTarget(evt: { graphic: Graphic; vertexinfo: any; target: Edit; }) {
    this.curentTarget = evt;
}

}

export = RightClickVertexContextMenu;
David Wilton
  • 344
  • 2
  • 11