View Full Version : Prevent default on chart context menu not working

23 Jun 2015, 9:04 AM
Hi all,

I've added a context menu to a chart segment but for some reason I am unable to prevent the default browser menu from also appearing.

I define my menu as this:

Ext.define('HistoryWorkSheet.view.ChartContextMenu', {
extend: 'Ext.menu.Menu',
config: {
productID: '',
productLevelInput: '',
parentPanelID: '',
filters: {}
constructor: function (config) {
this.initConfig(config); //mixes incoming config with pre-defined config
preventDefault: true,
alias: 'widget.chartcontextmenu',

items: [],
showItem: function (item, position) {
showMenu: function (level, id, position) {
var me = this;
refreshChart: function (level, id) {
alert('refresh ' + level);

and when I add my series I do this...

newSeries = {
type: me.chartType,
xField: 'product',
yField: [],
stacked: me.stacked,
preventDefault: true,
style: {
stroke: '#666666',
fillOpacity: 0.8
listeners: {

itemmousedown: function (item, e) {

var click = {0: 'left', 1: 'middle', 2: 'right'};

if (click[e.button] == 'right') {
var position = e.getXY();
... etc ...

for some reason the stopEvent and preventDefault are failing.
Or maybe there's another event firing that I need to catch?

Many thanks to anyone that has ideas on this.

Also maybe there's an easier way to add a context menu to a chart segment. This seems more difficult than it should be


23 Jun 2015, 1:43 PM
itemmousedown is not a browser event for the context menu. contextmenu is the browser event for handling that.

What component are you setting the itemmousedown listener to?

24 Jun 2015, 6:43 AM
I have it on a series for a chart.

newSeries = { type: me.chartType, xField: 'product', yField: [], stacked: me.stacked, preventDefault: true, style: { stroke: '#666666', fillOpacity: 0.8 }, listeners: { itemmousedown: function (item, e) { e.stopEvent(); e.preventDefault();

Basically I am dynamically adding series to various chart types. I need a context menu for any given segment of a chart. Let me know if there's an easier way of doing this.

The listener is added to the series and the series is added to the chart.



26 Jun 2015, 6:05 AM
I don't think that itemmousedown is going to work because you aren't going to be able to distinguish between which button was clicked. What I've done in this example is added a contextmenu listener to the Ext.chart.Chart element, delegating to element with a chart-sprite class (which I add to each of the surface items). This way, the menu is only display when you right-click on one of the data points of the chart.


26 Jun 2015, 6:43 AM
Thanks Tristan,that certainly prevents the browser menu from appearing. However, when the click event is fired in the contextmenu how do I determine which segment was selected?I have a stacked bar with multiple segments and I want the menu actions to only apply to a given segment.Your help is greatly appreciated!Lee

26 Jun 2015, 12:08 PM
Check out the fiddle below. I used a stacked bar chart and continued with the same contextmenu listener. Based on the target element of the mouse click, I check to see if the XY of that element is a valid item for the series. If the item is valid, I stop the event and show the menu.

At this point, item contains a lot of information that should have what you're looking for.



30 Jun 2015, 10:59 AM
Thanks for the reply...it very nearly works. However, it only works for the first item on the chart. e.g. If there are 5 bars on the chart the context menu only works for the first bar :-( It seems like there should be and easier way... Thanks Lee

30 Jun 2015, 11:29 AM
So I did manage to get it working with this:

listeners: {
render: function (cmp) {
cmp.el.on('contextmenu', function (evt, t) {
var x = evt.browserEvent.clientX;
var y = evt.browserEvent.clientY;
var me = this;
var chart = cmp.down('chart');
// clicked element
// target = Ext.get(t),

// xy position based on the element (sprite), not the mouse
xy = target.getXY();

var series = chart.series.get(0);

var item = series.getItemForPoint(xy[0] - chart.getX(), xy[1] - chart.getY());
if (item) {
createCtxMenu(item, x, y);

Its a little ugly and confusing but seems to work for stacked charts etc.
I have my charts within a panel that is dynamically added to the view. ie.A user can add/remove/resize charts and change the series/y axis etc on-the-fly.

Thanks again for the help...without the hints I would have never got it working.

2 Jul 2015, 8:10 AM
Thanks for providing your solution.

10 Aug 2017, 4:09 AM
This is still an issue and not working for ExtJS 6.x

This answer doesn't seem to work and fails getting sprite items. I can disable the content menu on the empty space on the chart but right clicking the bars still shows the browser context menu and I have to hold ALT or long hold the mouse button to see my menu (it's z-index is lower than the browser's contextmenu)

Any ideas?