TapTool on a Pie Chart Reopens all Previous Taps

Every time TapTool is used to open a URL, that URL will be reopened when I click anywhere on the plot. So the first wedge I click works fine, then whenever I click another wedge the URL is opened as well as the URLs of each previously clicked wedge. That whole collection of URLs that has been opened will also open if I click anywhere else on the plot.

However, if I click on a wedge, and then close the opened URL, and click the same wedge again, it will be unselected, and it’s URL won’t be opened when I click elsewhere.

        # Call the base implementation first to get a context
        context = super().get_context_data(**kwargs)
        obj = self.get_object()
    
        #factors and palette for factor_cmap function
        cfac = ['true', 'false']
        pal = ('#ef8a62', '#67a9cf')

        #the data which will be turned into a ColumnDataSource
        data = {'weight': [],
            'name': [],
            'bool': [],
            'start_angle': [],
            'end_angle': [],
            'url': []}

        #populating data based on the Django object of this DetailView
        for point in obj.points.all():
            data["name"].append(point.name)
            if point.boolean:
                data['bool'].append("true")
            else:
                data['bool'].append("false")
            data["url"].append(point.url)
            data["start_angle"].append(0)
            data["end_angle"].append(0)
            data["weight"].append(0)

        #wedge angle calculations
        percent = 1/len(data["name"]) * 100
        for i in range(len(data["weight"])):
            data["weight"][i] = percent
        
        radians1 = [radians((weight/100)*360) for weight in data["weight"]]

        start_angle = [radians(0)]
        prev = start_angle[0]
        for k in radians1[:-1]:
            start_angle.append(k + prev)
            prev = k + prev

        end_angle = start_angle[1:] + [radians(0)]

        data["start_angle"] = start_angle
        data["end_angle"] = end_angle

        #make the data into a bokeh compatible resource
        source = ColumnDataSource(data = data)

        #plotting
        p = figure(
            height=350,
            title="Pie Chart",
            toolbar_location=None,
            tools="hover,tap",
            tooltips="@name \n @url",
            x_range=(-0.5, 1.0),
        )

        p.wedge(
            x=0,
            y=1,
            radius=0.4,
            start_angle="start_angle",
            end_angle="end_angle",
            line_color="white",
            fill_color=factor_cmap('bool', pal, factors=cfac),
            legend_field="name",
            source=source,
        )

        #enable taptool
        taptool = p.select(type=TapTool)
        taptool.callback = OpenURL(url="@url")

        p.axis.axis_label = None
        p.axis.visible = False
        p.grid.grid_line_color = None

        script, div = components(p)

        context["script"] = script
        context["div"] = div
        return context

I’m happy to quickly investigate a complete Minimal Reproducible Example that I can actually copy and paste and run myself.

That said, TapTool.callback is a very old API, almost original to the library, that will probably be deprecated and removed at some point. There are newer and better approaches now. If you are interested to have events happen when glyphs are selected by tapping on them, then these days I would recommend using selection callbacks instead

https://docs.bokeh.org/en/latest/docs/user_guide/interaction/js_callbacks.html#customjs-for-selections

Then instead of the code I have, I’ll use:

        source.selected.js_on_change('indices',
            CustomJS(
                args=dict(source=source),
                code="""          
                window.open("@url" ,"_blank");
                """,
            )
        )

But I don’t know the syntax of this function, the javascript that runs on the site is opening “http://…com/@url” rather than the url of the selected wedge. How would I add the urls in js_on_change

The value of the URL in this case would be at

source.data.url[idx]

where idx is the integer selection index, stored in source.selected.indices There are several examples in the repo examples folder that show how to access the selection indices (note that there can be multiple selection indices if the tap hits multiple glyphs at a time, you’ll need to handle that possibility).

The problem with this new implementation and the old is that selections are persistent, at least in the pie chart. As in, I click it, and the rest of the chart is greyed out, it remains selected. Then if I click another wedge, it they are both selected then, and the rest are greyed out. And so the JS code to open the links of the selected indices of course will malfunction.

I’m looking into how to make selections behave differently. I’m wondering how the taptool can be used so that wedges don’t get selected, just to register a click and then unselect it.

the rest of the chart is greyed out, it remains selected.

Greyed out is just the default non-selection appearance. You can configure the non-selection appearance however you like:

Styling plot elements — Bokeh 3.4.1 Documentation

Then if I click another wedge, it they are both selected then, and the rest are greyed out.

You’ll have to describe the precise sequence of steps in more detail and maybe provide screen capture video. This description is not consistent with how selection has ever behaved. To get “both selected” you’d need to either:

  • hold down shift while tapping to perform an append-select
  • tap on multiple overlapping glyphs at once

If you add tap to the standard pie chart in Bokeh’s documentation (pie — Bokeh 3.4.1 Documentation) you’ll see that is not how it behaves on a pie chart. It’s as if every click is a shift click, which is why I think I had the original problem and why implementing callbacks didn’t solve the problem.

@Mark_Bezerra This appears to be a very new bug. Can you file a GitHub Issue with full details?

Noting that the problem seems confined to tap tool (e.g. box select does not misbehave) and is a new issue in 3.4.x (compare tap tool in this 3.3.x example vs the latest version). Until this can be fixed and 3.4.2 can be released your best bet is to downgrade to 3.3.x (but please do report the github issue as well).

Nevermind @Mark_Bezerra I have made the issue

Tap tool permanently in append mode · Issue #13831 · bokeh/bokeh · GitHub