# Programmatically trigger hover events with Dash

**URL:** <https://community.plotly.com/t/programmatically-trigger-hover-events-with-dash/42443>\
**Category:** Dash Python\
**Tags:** show-and-tell\
**Created:** [July 14, 2020, 12:02pm UTC](https://community.plotly.com/t/programmatically-trigger-hover-events-with-dash/42443 "2020-07-14T12:02:10Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![RenaudLN](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/renaudln/32/9041_2.png) [@RenaudLN](https://community.plotly.com/u/RenaudLN)\
**Post date:** [July 14, 2020, 12:02pm UTC](https://community.plotly.com/t/programmatically-trigger-hover-events-with-dash/42443/1 "2020-07-14T12:02:10Z")

</div>

I was trying for a little while to programmatically trigger hover events with Dash to do something like in [this post](https://community.plotly.com/t/2-graphs-1-hover/12588/4).

The problem was: I have a map with a route and to each point on this route correspond a certain number of metrics like speed and elevation as a function of time. I wanted to be able to hover the map and have the info about my metrics shown in the other plot as though I was hovering both at the same time.

I had seen the excellent codepen from @etienne in [this post](https://community.plotly.com/t/programmatically-trigger-hover-info-display-in-a-chart/14235) that would allow me to do this with Plotly.js but it was still a step further to get it to work with Dash. However after some trial and error I finally managed to use the Plotly.js functions from a `clientside_callback` in Dash to do what I intended and I would like to share it with the community.

 ![triggered_hover2](https://us1.discourse-cdn.com/flex024/uploads/plot/original/2X/8/874cb3e77a3aaf1a7c70cccfd1579583e737ac6e.gif)

And here’s the code (and in particular the clientside function) to get this minimal example working 🙂

`app.py`

```python
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State, ClientsideFunction

import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots

app = dash.Dash()
app.config.suppress_callback_exceptions = True
app.css.config.serve_locally = True
app.scripts.config.serve_locally = True

time = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
distance = [0,0.004,0.007,0.011,0.016,0.022,0.028,0.036,0.042,0.048,0.052,0.059,0.066,0.072,0.078,0.084,0.09,0.099,0.109,0.118,0.125]
speed = [14.696,15.328,10.439,19.156,18.624001,17.870001,26.912001,27.907,22.976,16.390001,18.188002,27.021,21.201,23.300001,20.500999,22.988001,23.959999,31.730001,31.956001,31.43,21.372]
latitude = [-38.17793652,-38.17790629,-38.17790202,-38.17791691,-38.17793357,-38.17796016,-38.17800478,-38.17805941,-38.17810737,-38.17814195,-38.17817029,-38.17817777,-38.17820753,-38.17824037,-38.17826873,-38.17827853,-38.17828449,-38.17830426,-38.17837713,-38.17843687,-38.17848226]
longitude = [176.3022128,176.3021731,176.3021367,176.3020748,176.3020026,176.3019411,176.3018562,176.3018142,176.3017969,176.3017735,176.3017327,176.3016405,176.3015786,176.3015091,176.3014366,176.3013507,176.3012592,176.3011339,176.3010612,176.30099,176.3009314]
elevation = [587.94,586.76,583.71,580.86,577.35,571.41,563.5,557.79,553.01,550.37,545.63,541.79,536.48,534.84,531.5,530.14,529.69,526.94,523.21,521.83,519.1]

map_figure = px.line_mapbox(
    lat=latitude,
    lon=longitude,
    custom_data=[time],
    mapbox_style="open-street-map",
    zoom=17
)
map_figure.update_layout(margin=dict(b=0,t=0,r=0,l=0))

metrics_figure = make_subplots(specs=[[{"secondary_y": True}]])
metrics_figure.add_trace(
    go.Scatter(
        x=time,
        y=elevation,
        name="Elevation",
        hovertemplate="Elevation: %{y}m",
    )
)
metrics_figure.add_trace(
    go.Scatter(
        x=time,
        y=speed,
        name="Speed",
        hovertemplate="Speed: %{y}m",
    ),
    secondary_y=True,
)
metrics_figure.update_layout(hovermode="x unified", margin=dict(b=20,t=20,r=20,l=20))

app.layout = html.Div(children=[
    html.H2("Metrics"),
    dcc.Graph(id="metrics_graph", figure=metrics_figure),
    html.H2("Map"),
    dcc.Graph(id="map_graph", figure=map_figure),
    html.Div(id="dummy"),
])

app.clientside_callback(
    ClientsideFunction(namespace="clientside", function_name="trigger_hover"),
    Output("dummy", "data-hover"),
    [Input("map_graph", "hoverData")],
)

if __name__ == " __main__":
    app.run_server(debug=True)

```

`assets/script.js`

```javascript
if (!window.dash_clientside) {
    window.dash_clientside = {};
}
window.dash_clientside.clientside = {
    trigger_hover: function(hoverData) {
        var myPlot = document.getElementById("metrics_graph")
        if (!myPlot.children[1]) {
            return window.dash_clientside.no_update
        }
        myPlot.children[1].id = "metrics_graph_js"

        if (hoverData) {
            if (Array.isArray(hoverData.points[0].customdata)) {
                var t = hoverData.points[0].customdata[0]
            } else {
                var t = hoverData.points[0].customdata
            }
            t = Math.round(t*10)/10
            Plotly.Fx.hover("metrics_graph_js", {xval: t, yval:0})
        }
        return window.dash_clientside.no_update
    }
}

```

---

<div class="post-metadata">

**Author:** ![chriddyp](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/chriddyp/32/16855_2.png) [@chriddyp](https://community.plotly.com/u/chriddyp)\
**Post date:** [July 14, 2020, 4:09pm UTC](https://community.plotly.com/t/programmatically-trigger-hover-events-with-dash/42443/2 "2020-07-14T16:09:19Z")

</div>

🏆 🏆 Very nice!!

---

<div class="post-metadata">

**Author:** ![DanielPark\_91](https://avatars.discourse-cdn.com/v4/letter/d/fbc32d/32.png) [@DanielPark\_91](https://community.plotly.com/u/DanielPark_91)\
**Post date:** [April 23, 2021, 4:46am UTC](https://community.plotly.com/t/programmatically-trigger-hover-events-with-dash/42443/3 "2021-04-23T04:46:50Z")

</div>

Hi I want to use your code, but I can’t understand from “assets/script.js”

I’m using Jupyter notebook, I could make two graphs (map and graph) on Dash.

Can you explain how I can use your code below assets/script.js?

```auto
map_figure = px.line_mapbox(df_GPS,
    lat=df_GPS["Lat[1]"].tolist(),
    lon=df_GPS["Long[1]"].tolist(),
    hover_name= df_GPS["dnt"].dt.strftime("%m-%d %H:%M:%S"),
    custom_data=["time"],
    mapbox_style="open-street-map",
    zoom=10
)

map_figure.update_layout(margin=dict(b=0,t=0,r=0,l=0))
map_figure.show(renderer='notebook')

```

```auto
y_list =["Speed","Altitude"]

metrics_figure = make_subplots(specs=[[{"secondary_y": True}]])

metrics_figure.add_trace(
    go.Scatter(
        x=df_GPS["dnt"].dt.strftime("%m-%d %H:%M:%S"),
        y=df_GPS[y_list[0]],
        name=y_list[0],
        line_color=mcolors[0],
        hovertemplate= "%{y}"))

layout = {'xaxis':dict(domain=[0,1-(len(y_list)-2)*0.09]),
          'yaxis':dict(title=y_list[0],titlefont=dict(color=mcolors[0]),
                       tickfont=dict(color=mcolors[0]),showgrid=True)}
n=2
for var_y in y_list[1::]:
    metrics_figure.add_trace(
        go.Scatter( 
        x=df_GPS["dnt"].dt.strftime("%m-%d %H:%M:%S"),
        y=df_GPS[var_y],
        name=var_y,
        yaxis ='y'+str(n),
        line_color=mcolors[n],
        hovertemplate= "%{y}"
        ))
                 
    layout['yaxis'+str(n)] = dict(title=var_y, titlefont=dict(color=mcolors[n]),
                                  tickfont=dict(color=mcolors[n]),
                                  anchor="free",
                                  overlaying="y",
                                  side="right",
                                  position=1-(n-2)*0.09,
                                  showgrid=False)
    n+=1
    
metrics_figure.update_layout(**layout,hovermode="x unified", margin=dict(b=20,t=20,r=20,l=20))

```

```auto
app = dash.Dash( __name__ )
app.config.suppress_callback_exceptions = True
app.css.config.serve_locally = True
app.scripts.config.serve_locally = True

```

```auto
app = dash.Dash( __name__ )
app.layout = html.Div(children=[
    html.H2("Map"),
    dcc.Graph(id="map_graph",figure=map_figure),
    html.H2("Metrics"),
    dcc.Graph(id="metrics_graph",figure=metrics_figure),
    html.Div(id="dummy")
])

app.clientside_callback(
    ClientsideFunction(namespace="clientside", function_name="trigger_hover"),
    Output("dummy", "data-hover"),
    [Input("map_graph", "hoverData")],
)

if __name__ == ' __main__':
    app.run_server(debug=True,use_reloader=False)
    

```

I could run my code by this part.  
and I met an error (Cannot read property ‘trigger\_hover’ of undefined) on Dash.

Plz Help me

---

<div class="post-metadata">

**Author:** ![RenaudLN](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/renaudln/32/9041_2.png) [@RenaudLN](https://community.plotly.com/u/RenaudLN)\
**Post date:** [April 23, 2021, 4:55am UTC](https://community.plotly.com/t/programmatically-trigger-hover-events-with-dash/42443/4 "2021-04-23T04:55:32Z")

</div>

In the same folder where your `app.py` lives, create an `assets` folder in which you add a `scripts.js` file where you put the code I wrote above. You need to make sure the ids match between your layout and what’s in `scripts.js`.

---

<div class="post-metadata">

**Author:** ![DanielPark\_91](https://avatars.discourse-cdn.com/v4/letter/d/fbc32d/32.png) [@DanielPark\_91](https://community.plotly.com/u/DanielPark_91)\
**Post date:** [June 2, 2021, 11:05pm UTC](https://community.plotly.com/t/programmatically-trigger-hover-events-with-dash/42443/5 "2021-06-02T23:05:04Z")

</div>

Hi.  
Thank you. It works well.  
I have one more question.  
Is it possible to change input to output?  
I mean (input :Metrics figure, output : map figure)  
As I move my mouse point on a metrics figure, I want to see a location on a map by a hover pop-up.

---

<div class="post-metadata">

**Author:** ![yanndavin](https://avatars.discourse-cdn.com/v4/letter/y/50afbb/32.png) [@yanndavin](https://community.plotly.com/u/yanndavin)\
**Post date:** [November 2, 2021, 9:07pm UTC](https://community.plotly.com/t/programmatically-trigger-hover-events-with-dash/42443/6 "2021-11-02T21:07:57Z")

</div>

Very nice 😀. Do you know if it is possible to make it works in reversal direction ?  
Meaning mouse move on the metrics, programmatic fx hover on the map.  
It is not obvious to find the correct properties to make Ploty.Fx.hover function works on map\_graph. I’ve tried xval, yval with longitude and latitude without success. So if anybody has a idea I’ll be happy 🙂

---

<div class="post-metadata">

**Author:** ![RenaudLN](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/renaudln/32/9041_2.png) [@RenaudLN](https://community.plotly.com/u/RenaudLN)\
**Post date:** [November 2, 2021, 9:54pm UTC](https://community.plotly.com/t/programmatically-trigger-hover-events-with-dash/42443/7 "2021-11-02T21:54:32Z")

</div>

Hey @yanndavin have a look at this topic, I think you’ll have to go with `curveNumber` and `pointNumber`.

> [@Coordinating a Dash line chart with Mapbox graph](https://community.plotly.com/t/coordinating-a-dash-line-chart-with-mapbox-graph/55308):
>
> I am trying to visualize workout data and I’ve uploaded some .fit files from my fitness watch. I have 2 graphs: a line plot containing speed, heart rate, running power, etc… and a Mapbox graph containing GPS coordinates. I would like to be able to hover over parts of the heart rate line plot, then see which coordinate that part is associated with. Is there a way to coordinate the 2 charts together? Preferably without having to use the Mapbox API multiple times (don’t want to overuse my license)…

---

<div class="post-metadata">

**Author:** ![yanndavin](https://avatars.discourse-cdn.com/v4/letter/y/50afbb/32.png) [@yanndavin](https://community.plotly.com/u/yanndavin)\
**Post date:** [November 4, 2021, 8:45pm UTC](https://community.plotly.com/t/programmatically-trigger-hover-events-with-dash/42443/8 "2021-11-04T20:45:43Z")

</div>

Thanks you @RenaudLN `curveNumber` and `pointNumber` looks promising. Like @azureity I’m stuck now on the `Invalid LngLat obj: (NaN, ...)`, after quick look inside the debugger a variable is undefined for a unknown reason which causes effective calculation of the longitude to raise a exception (see screenshot).  
I’ve not yet found a solution.

 ![image](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/4/a/4a93f4418e867eac1dda5d19928610d8ccdce6e0.png)

---

<div class="post-metadata">

**Author:** ![yanndavin](https://avatars.discourse-cdn.com/v4/letter/y/50afbb/32.png) [@yanndavin](https://community.plotly.com/u/yanndavin)\
**Post date:** [November 4, 2021, 9:52pm UTC](https://community.plotly.com/t/programmatically-trigger-hover-events-with-dash/42443/9 "2021-11-04T21:52:13Z")

</div>

@RenaudLN I’ve finally found that you can simply pass longitude and latitude as `xval`, `yval`:  
` Plotly.Fx.hover("map_graph_js", {xval: lon, yval: lat}, "mapbox")`

---

<div class="post-metadata">

**Author:** ![schloe](https://avatars.discourse-cdn.com/v4/letter/s/48db29/32.png) [@schloe](https://community.plotly.com/u/schloe)\
**Post date:** [June 29, 2022, 8:17am UTC](https://community.plotly.com/t/programmatically-trigger-hover-events-with-dash/42443/10 "2022-06-29T08:17:22Z")

</div>

I found this thread almost a year later while running into the same problem…  
Unfortunately i cannot hover via xval/yval since my coords are not unique, so matching the point only via coords is not enough.

The following unfortunately does not work on the map. It creates a single hover label and a some point but not the one specified with `pointNumber`.

```auto
Plotly.Fx.hover(graph_id, {curveNumber: curveNumber, pointNumber:pointNumber}, "mapbox")

```

With this, i.e. second arg as an array, i get an Error: `Invalid LngLat object: (NaN, 48.*)`

```auto
Plotly.Fx.hover(graph_id, [{curveNumber: curveNumber, pointNumber:pointNumber}], "mapbox")

```

Anyone has a solution here?

---

<div class="post-metadata">

**Author:** ![MatthiasHauth](https://avatars.discourse-cdn.com/v4/letter/m/ecc23a/32.png) [@MatthiasHauth](https://community.plotly.com/u/MatthiasHauth)\
**Post date:** [July 13, 2023, 12:04pm UTC](https://community.plotly.com/t/programmatically-trigger-hover-events-with-dash/42443/11 "2023-07-13T12:04:05Z")

</div>

Very nice example!

If i understand correctly, the callback is triggered for every new hover on the MapBox graph. Do you know if your MaxBox token is debited for every hover then? Or only just once to generate the map?
