Skip to content

plotly_doubleclick also triggers plotly_click #1546

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

Closed
druvisc opened this issue Apr 3, 2017 · 5 comments
Closed

plotly_doubleclick also triggers plotly_click #1546

druvisc opened this issue Apr 3, 2017 · 5 comments

Comments

@druvisc
Copy link

druvisc commented Apr 3, 2017

Double clicking on something drawn always triggers a 'plotly_click' event as well.

http://codepen.io/anon/pen/EWrrwW

In my actual scenario, the 'plotly_click' event almost always gets triggered (also when clicking on the plot's 'background' where nothing is drawn).
Is it possible to make it into an actual 'double click' event (adding a delay after the 'click' event)?

@monfera monfera self-assigned this Apr 7, 2017
@monfera
Copy link
Contributor

monfera commented Apr 7, 2017

@druvisc thanks for the report! It's indeed the case that currently, a plotly_click event is also raised. We could make it so that it doesn't. But, since a double-click physically starts with a single mouse click, and within a short interval, followed by another click, we'd need to wait at least as much, before plotly.js could tell apart whether it's a single click, or just the first click in a double-click. plotly_click is now low latency and for some uses it can be beneficial.

Therefore we're planning to introduce a new plotly.js event called plotly_singleclick that would be of a higher latency than plotly_click because it first needs to know that it won't be a double-click, but helpful for general use cases when a couple hundred milliseconds of latency doesn't matter. We'd still keep around the current plotly_click as it works now, as well as of course plotly_doubleclick.

For the moment, this logic can be done on your end, either by capturing a plotly_click and not invoking your click callback if a plotly_doubleclick is subsequently registered, or follow a workaround by @etpinard where you detect a double-click event yourself: http://codepen.io/etpinard/pen/JWaEXG?editors=0010

@etpinard
Copy link
Contributor

etpinard commented Apr 7, 2017

Referencing other event discussions in #145

@sardbaba
Copy link

@druvisc please take a look at the following code, which uses (and require) d3js:

plotlyClickEvents() {
    /**
     * Distinguish between single and double click
     * @see http://bl.ocks.org/ropeladder/83915942ac42f17c087a82001418f2ee
     */
    function clickcancel() {
        var dispatcher = d3.dispatch('d3_plotly_singleclick', 'd3_plotly_doubleclick');
        function cc(selection) {
            var down, tolerance = 5, last, wait = null, args;

            // euclidean distance
            function dist(a, b) {
                return Math.sqrt(Math.pow(a[0] - b[0], 2) + Math.pow(a[1] - b[1], 2));
            }

            selection.on('mousedown', function() {
                down = d3.mouse(document.body);
                last = +new Date();
                args = arguments;
            });

            selection.on('mouseup', function() {
                if (dist(down, d3.mouse(document.body)) > tolerance) {
                    return;
                }
                else {
                    if (wait) {
                        window.clearTimeout(wait);
                        wait = null;
                        dispatcher.apply("d3_plotly_doubleclick", this, args);
                    }
                    else {
                        wait = window.setTimeout((function() {
                            return function() {
                                dispatcher.apply("d3_plotly_singleclick", this, args);
                                wait = null;
                            };
                        })(), 300);
                    }
                }
            });
        };

        // Copies a variable number of methods from source to target.
        var d3rebind = function(target, source, method) {
            var i = 1, n = arguments.length;
            while (++i < n) target[method] = d3_rebind(target, source, source[method]);
            return target;
        };

        // Method is assumed to be a standard D3 getter-setter:
        // If passed with no arguments, gets the value.
        // If passed with arguments, sets the value and returns the target.
        function d3_rebind(target, source, method) {
            return function() {
                var value = method.apply(source, arguments);
                return value === source ? target : value;
            };
        }

        return d3rebind(cc, dispatcher, 'on');
    }

    return clickcancel();
}


var item = null;

d3.select('#barchart-selector-of-your-choice')
    .select('g.barlayer')
        .selectAll('.point > path').each(function(e) {

    item = d3.select(this);

    // @NOTE: Without this attribute is not possibile to listen for mouse events.
    item.attr('pointer-events', 'all');

    cc = plotlyClickEvents();
    item.call(cc);

    cc.on('d3_plotly_singleclick', (d, index) => {
        // d['p'] is the index in the x-axis; d['s'] is the value of the y-axis
        console.log("d3_plotly_singleclick", d)
    });

    cc.on('d3_plotly_doubleclick', (d, index) => {
        // d['p'] is the index in the x-axis; d['s'] is the value of the y-axis
        console.log("d3_plotly_doubleclick", d)
    });
});

@etpinard etpinard mentioned this issue Jan 12, 2018
@alexcjohnson
Copy link
Collaborator

related issue I noticed while reviewing #2200 - we should either not emit the second click or do so before the doubleclick event.

Having the doubleClick handled before click (in Fx.click) is both different from native events (which always seem to put the doubleClick last, though some browsers - cough IE cough - don't emit the second click at all) AND potentially incorrect: if Plotly.relayout is synchronous, then Fx.click will make it look like you clicked on whatever point happens to be under your cursor after autoranging, rather than the one you actually clicked on.

@gvwilson
Copy link
Contributor

Hi - this issue has been sitting for a while, so as part of our effort to tidy up our public repositories I'm going to close it. If it's still a concern, we'd be grateful if you could open a new issue (with a short reproducible example if appropriate) so that we can add it to our stack. Cheers - @gvwilson

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

No branches or pull requests

6 participants