Skip to content

Add support for clickable hover text or a per pt onclick attribute #998

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

Open
etpinard opened this issue Sep 29, 2016 · 52 comments
Open

Add support for clickable hover text or a per pt onclick attribute #998

etpinard opened this issue Sep 29, 2016 · 52 comments
Labels
feature something new P3 backlog

Comments

@etpinard
Copy link
Contributor

Users can put links inside hover labels, but when user try to click the link, the hover label obviously disappears. So perhaps we could add optional “sticky” hover labels, where you click and the hover label is persistent until you click again?

Defining what sticky means will be tricky. It probably doesn't apply to every situation. Maybe we could add it as a new layout.hovermode e.g. 'hovermode: 'sticky'.

So, maybe instead we could define a linkonclick attribute e.g. linkonclick: ['https://plot.ly/~empet/101', 'https://plot.ly', /* ... one link per data pt */] that way clicking on a data pt would open the link instead of hovering on the data pt -> move mouse over link in hover label -> click on it.

cc @jackparmer

@john-soklaski
Copy link
Contributor

We definitely would have use for a hover label that the user can interact with. There is quite a bit of information in our hover labels (5-6 lines of text), and users would often like to copy and paste some text from the hover label, or potentially click a link.

@jackparmer
Copy link
Contributor

@john-soklaski what do you think the right interaction is for allowing a user to select copy paste what is in a hover tag?

@john-soklaski
Copy link
Contributor

@jackparmer I think persisting the hover label if a user moves the mouse cursor along the arrow to the hoverlabel makes sense (with hovermode: closest)

@maresk
Copy link

maresk commented Oct 14, 2016

@jackparmer I will second this feature request in the python API. Our clients would like to be able to interact with content related to a particular data point so ss far as interaction goes, the text should persist, and a hyperlink placed in the text should be clickable.

@latorrefabian
Copy link

+1

1 similar comment
@dr-stringfellow
Copy link

+1

@jackparmer
Copy link
Contributor

jackparmer commented Feb 15, 2017

@john-soklaski , @maresk , @latorrefabian , @maierbenedikt - you may be interested in discussion here, Annotations that show & hide on clicking data: #1266

@alexcjohnson
Copy link
Collaborator

And see the implementation of clicktoshow in #1265 - at some point we do intend to implement a way to generate "sticky" annotations programmatically on clicking a data point but for now, as long as you don't have too much data you can do it the other way around: pre-generate all the annotations you might want and link them to appear on clicking the appropriate data points.

@slremy
Copy link

slremy commented May 4, 2017

Hello all!
Am I missing something fundamental here? Is there a purpose of being able to have hyperlinks in the text if you can't click them?

image

@alexcjohnson
Copy link
Collaborator

Am I missing something fundamental here? Is there a purpose of being able to have hyperlinks in the text if you can't click them?

We support text in a lot of different contexts, and in most of the other contexts the links are clickable. So it would require special code to disable link creation within the unclickable contexts, and that extra complexity seemed unnecessary since really, is there a purpose to adding hyperlinks that you can't click? 😉

@slremy
Copy link

slremy commented May 5, 2017

That makes sense!

@PaNDanese
Copy link

what do you think the right interaction is for allowing a user to select copy paste what is in a hover tag?

@jackparmer I think clicking on the marker itself would be ideal to toggle the stickiness of the hover tag.

  • Click on the marker and the hover tag persists and you can then copy/paste hover tag-text and click on hyperlinks in the hover tag
  • Click on the marker again and the hover tag "unsticks".

+1 for utility

@wroscoe
Copy link

wroscoe commented Jul 7, 2017

+1 for this. This would enable users to dig into the data by linking other related charts. I like the simple solution proposed by @pdanese

@slremy
Copy link

slremy commented Aug 17, 2017

It seems as if there may already a solution in community.plot.ly

To me it seems that if you knew which datum was clicked, then you could window.open(datum.uri). It's probably not that easy.. but the fiddle is compelling.

I can't quite read tease it out of the docs what it's actually saying :(

@newuser357
Copy link

Hello, has this been completed yet? Currently working on a project where I want users to be able to click the annotations and copy them to the clipboard.

@nistrup
Copy link

nistrup commented Jul 19, 2019

I would love to have this feature as well!

@bill10
Copy link

bill10 commented Aug 19, 2019

looks like this is still open? any updates?

@rusiano
Copy link

rusiano commented Feb 4, 2020

+1

1 similar comment
@steffon-atg
Copy link

+1

@kamikaze942
Copy link

+1 need stickiness

@jackparmer
Copy link
Contributor

This is not a large project but obviously hasn't found its way to the top of the priority queue for a while. If any company would like to partner with us on this, we'd be interested in discussing!
https://plot.ly/products/consulting-and-oem/

@AniWar
Copy link

AniWar commented May 13, 2020

(For 3D chart)
I was trying out some complex keyboard bindings (which didn’t work), and accidently I found this .
Just double click on markers (which selects text) , then press ctrl+C.
markerData

@josemonsalve2
Copy link

+1

@baddymaster
Copy link

+1

This would be very useful for data analysis. And unfortunately the hack suggested by @AniWar doesn't seem to work anymore.

@bmurtagh01
Copy link

+1

1 similar comment
@bschilder
Copy link

+1

@therhaag
Copy link

Hi - stumbled upon this when looking for a way to follow a URL that's in the hover text. The workaround proposed by @keseldude looks like it could work for me, but I don't understand how to use it. Could anyone please elaborate?

@GabeNicholson
Copy link

Any update on this?

@sebastien-plutniak
Copy link

+1, I am also in need of this feature

@philipjames44
Copy link

+1

@JohnScolaro
Copy link

+1

3 similar comments
@leijer
Copy link

leijer commented Oct 24, 2023

+1

@jerpint
Copy link

jerpint commented Feb 15, 2024

+1

@Simply-Connected-LLC
Copy link

+1

@gvwilson gvwilson self-assigned this Jun 5, 2024
@natearoe
Copy link

natearoe commented Jun 7, 2024

+1

3 similar comments
@irialagoportela
Copy link

irialagoportela commented Jun 21, 2024

+1

@sudughonge
Copy link

+1

@bartosz-nawrotek-brainly

+1

@gvwilson gvwilson removed their assignment Aug 2, 2024
@plaffitte
Copy link

+1

@npinter
Copy link

npinter commented Aug 7, 2024

I managed to find a workaround to make every hoverbox sticky. Just click on the datapoint to make the hoverbox sticky. Remove it by clicking the hoverbox or the datapoint again.

The trick was to make a copy of the hoverlayer <g></g> tag and move it to a new hoverlayer in the second <svg> object where the axes of the plot are stored. The persistent-hoverlayer is then placed after the <g></g> tag with the shapelayer class.

I generate the plot in Python and send it via POST to my HTML template. But the code should work for other implementations as well. Add this function inside your <script></script> element:

function setupPersistentHover(plotDiv) {
    const mainSvgs = plotDiv.querySelectorAll('.main-svg');
    if (mainSvgs.length === 0) {
        console.error("No main SVG elements found in plot");
        return;
    }

    const targetSvg = mainSvgs[1];
    const layerAbove = targetSvg.querySelector('.layer-above');
    if (!layerAbove) {
        console.error("Layer-above element not found in plot");
        return;
    }

    let persistentHoverLayer = layerAbove.querySelector('.persistent-hoverlayer');
    if (!persistentHoverLayer) {
        persistentHoverLayer = document.createElementNS("http://www.w3.org/2000/svg", "g");
        persistentHoverLayer.classList.add("persistent-hoverlayer");
        const shapelayer = layerAbove.querySelector('.shapelayer');
        if (shapelayer) {
            shapelayer.after(persistentHoverLayer);
        } else {
            layerAbove.appendChild(persistentHoverLayer);
        }
    }

    plotDiv.on('plotly_click', function(data) {
        const hoverLayer = plotDiv.getElementsByClassName("hoverlayer")[0];
        if (hoverLayer) {
            const hoverBox = hoverLayer.getElementsByClassName("hovertext")[0];
            if (hoverBox) {
                const existingHoverBox = Array.from(persistentHoverLayer.children).find(child =>
                    child.textContent === hoverBox.textContent
                );

                if (existingHoverBox) {
                    existingHoverBox.remove();
                } else {
                    const persistentHoverBox = hoverBox.cloneNode(true);
                    persistentHoverBox.style.pointerEvents = 'all';

                    // generate a unique id for the hover box
                    const hoverBoxId = 'hover-' + Date.now();
                    persistentHoverBox.setAttribute('id', hoverBoxId);

                    persistentHoverBox.addEventListener('click', function(e) {
                        e.stopPropagation();
                        this.remove();
                    });

                    persistentHoverLayer.appendChild(persistentHoverBox);
                }
            }
        }
    });
}

You need to call the function after the plot was generated:

$('#features_plot').html(data);
const featurePlotDiv = document.getElementById('features_plot').getElementsByClassName('js-plotly-plot')[0];
if (featurePlotDiv) {
    setupPersistentHover(featurePlotDiv);
}

This might not be the best practice solution (and I'm not a webdev ;) ) but it works!

EDIT:
added the function to make all hoverboxes sticky

@gvwilson gvwilson added the P3 backlog label Aug 8, 2024
@astro-manny
Copy link

The solution by @npinter works like a charm for my use case. Thank you 🙏❤️
I use Plotly in Grafana through the ae3e-plotly-panel plugin.

@janosh
Copy link

janosh commented Aug 14, 2024

has anyone figured out how to do this in python?

@philipjames44
Copy link

Saw this was closed as completed? Do we have a PR/version we can integrate?

@schoukah
Copy link

Saw this was closed as completed? Do we have a PR/version we can integrate?

Also wondering why this was closed,

@dynobo
Copy link

dynobo commented Dec 16, 2024

Also wondering why this was closed,

My best guess is that @gvwilson considered the workaround from this comment as a proper user side "solution".

In my opinion, the workaround on user side should not be considered as solution of this issue, because

  1. It requires significant implementation on user side. Solving it in plotly itself seems more reasonable and future proof.
  2. This workaround will be very difficult to find (hidden in comment of an issue which was closed without explicitly stating a reason for closing).

I'd strongly vote for reopening this issue, but the bare minimum would be stating a reason for closing it.

@gvwilson , could you please comment on this?

@gvwilson gvwilson reopened this Dec 16, 2024
@dynobo
Copy link

dynobo commented Dec 18, 2024

Thanks for reopening! ❤️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature something new P3 backlog
Projects
None yet
Development

No branches or pull requests