Distinguishing a double tap from a tap

I’m working on a visualization that has a tap event and a doubletap event. The challenge is that double tapping also triggers the tap event. Is there a simple way to keep the doubletap distinct without setting off the tap event? In the absence of that, is it possible to replace the doubletap event with some type of right click event?

I am using Bokeh 3.4. Here’s an example of my code. Tap moves the red star and DoubleTap moves the blue star. I want to move the blue star without moving the red star.

from bokeh.plotting import figure
from bokeh.models import CustomJS

import panel as pn

x = list(range(1, 10))
y = list(1 for i in range(1, 10))

p = figure(height=130, width=1800)
p.line(x=x, y=y)

star_location = 1
red = p.scatter(x=star_location, y=1, marker="star", size=15, color="red")
blue = p.scatter(x=star_location, y=1, marker="star", size=15, color="blue")

red_callback = CustomJS(
    args=dict(red=red),
    code="""
    console.log(cb_obj.x)
    red.glyph.x = cb_obj.x
""",
)

blue_callback = CustomJS(
    args=dict(blue=blue),
    code="""
    console.log(cb_obj.x)
    blue.glyph.x = cb_obj.x
""",
)

p.js_on_event("tap", red_callback)
p.js_on_event("doubletap", blue_callback)


layout = pn.Column(p)

layout.servable()

Use panel serve <file name> to run.

@Stefeni_Butterworth One idea is to have a setTimeout() on the single click event callback and when the pause has elapsed check if double click event has been triggered recently. In my example below I use 500 ms as delay. I use performance.now() to get time and I store the double click time stamp in the glyph tags argument. In the single click event callback I check time difference between the single click event and the double click event. Inspired by discussion on SO.

red_callback = CustomJS(
    args=dict(red=red, blue=blue),
    code="""
    console.log('red cb');

    setTimeout(() => {
        const t = performance.now();
        const dbl_timestamp = blue.tags.length > 0 ? blue.tags[0] : 0;
        console.log(dbl_timestamp);
        console.log(t-dbl_timestamp);
        if ( (t-dbl_timestamp) > 500 ) {
            console.log('Single click');
            red.glyph.x = cb_obj.x
        } else {
            console.log('Dbl click');
        }
    }, 500);
""",
)

blue_callback = CustomJS(
    args=dict(blue=blue),
    code="""
    console.log('blue cb');
    blue.tags = [performance.now()];
    blue.glyph.x = cb_obj.x;
""",
)
1 Like

That works beautifully. Thanks so much!