Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Click event only generated when clicking in specific areas of Bar graph #5383

Open
francisco-pjbank opened this issue Aug 10, 2023 · 4 comments
Labels
type: bug Something isn't correct or isn't working
Milestone

Comments

@francisco-pjbank
Copy link

francisco-pjbank commented Aug 10, 2023

This issue came out from a discussion on panel discourse, link here. I will reproduce below the main parts of it.

There is an integration problem between panel and plotly when trying to receive click events upon clicking on the bar graph using plotly. The event is only triggered when clicking in the space between the bars and not inside the Bar. if sizing_mode is not used (check the MRE below), situation gets even worse. Same reasoning holds true if orientation of the Bar changes from horizontal to vertical.

Relevant software version info

pandas 1.5.3
panel 1.2.0
plotly 5.15.0
plotly-express 0.4.1
python 3.9.17
ubuntu 20.04

Description of expected behavior and the observed behavior

Click events should only occur when clicking inside the Bar independent of the size mode or orientation used.
Currently events are generated when clicking close to the Bar in the space between bars. If no size mode is used or orientation is changed, than click events are not triggered or occur randomly.

Complete, minimal, self-contained example code that reproduces the issue

import plotly.express as px
import pandas as pd
import panel as pn
from panel.template.react import ReactTemplate

df = pd.DataFrame(data = {'month':['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'],'value':[10,15,20,5,12,6,21,8,9,3,11,17]})

fig=px.bar(x=df['month'], y=df['value'])

def on_click(event):
    if event.name == 'click_data':
        if event.obj is not None:
            print("on_click", event.obj.click_data)
            print("on_click old", event.old)
            print("on_click new", event.new)


plot_panel = pn.pane.Plotly(fig, 
                            config={"responsive": True},
                            sizing_mode="scale_both"
                            )

plot_panel.param.watch(on_click, ["click_data"],onlychanged=False)

pn.Column(plot_panel).servable()

Stack traceback and/or browser JavaScript console output

N/A

Screenshots or screencasts of the bug in action

It is pretty easy to reproduce so I think a screenshot is not necessary.

@MarcSkovMadsen
Copy link
Collaborator

I've been able to reproduce the issue. See the mentioned discourse discussion.

@MarcSkovMadsen MarcSkovMadsen added the type: bug Something isn't correct or isn't working label Aug 10, 2023
@MarcSkovMadsen MarcSkovMadsen added this to the next milestone Aug 10, 2023
@MarcSkovMadsen
Copy link
Collaborator

Here is another issue which also has issues with mouse clicks. It might be related.

#5195

@sblowers
Copy link

sblowers commented Jan 22, 2024

Hi I've been hitting the exact same problem and been bashing my head all day trying to get it to work. I think the root cause lies within Plotly library not registering click events correctly within the ShadowDOM -> plotly/plotly.js#6108

I have a workaround for now which was to download the plotly.js file from https://github.com/plotly/plotly.js/blob/v2.25.2/dist/plotly.js and then comment out the lines 7914-7918:

module.exports = function click(gd, evt, subplot) {
  var annotationsDone = Registry.getComponentMethod('annotations', 'onClick')(gd, gd._hoverdata);

  // fallback to fail-safe in case the plot type's hover method doesn't pass the subplot.
  // Ternary, for example, didn't, but it was caught because tested.
// !!! COMMENT THIS OUT to prevent retrigger of hover() on click !!!
//   if (subplot !== undefined) {
//     // The true flag at the end causes it to re-run the hover computation to figure out *which*
//     // point is being clicked. Without this, clicking is somewhat unreliable.
//     hover(gd, evt, subplot, true);
//   }

  function emitClick() {
    gd.emit('plotly_click', {
      points: gd._hoverdata,
      event: evt
    });
  }
  if (gd._hoverdata && evt && evt.target) {
    if (annotationsDone && annotationsDone.then) {
      annotationsDone.then(emitClick);
    } else emitClick();

    // why do we get a double event without this???
    if (evt.stopImmediatePropagation) evt.stopImmediatePropagation();
  }
};

Then I added to my app with pn.extension("plotly", js_files={'plotly_patched': 'assets/plotly-2.25.2_patched.js'}) (and serving that assets directory with panel serve app.py --show --static-dirs assets=./assets) and the clicks on plots seem work as expected again. I have no idea if this will cause unintended consequences with more complex plots and other functionality but it allowed me to proceed with what I was working on.

@philippjfr
Copy link
Member

Thanks for tracking this down @sblowers, I'll try to see if there is a way to this from within the panel.js bundle.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug Something isn't correct or isn't working
Projects
None yet
Development

No branches or pull requests

4 participants