Skip to content
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

[FEATURE] Access to know whether user ctrl-clicks, shift-clicks, or command-clicks in CustomJS callback #12532

Closed
monadandan opened this issue Oct 31, 2022 · 1 comment · Fixed by #13132

Comments

@monadandan
Copy link

monadandan commented Oct 31, 2022

Problem description

I am trying to make a tap tool with two different behaviors depending on whether the user is clicking on a point or control + clicking a point.

I would like this so that the user can tap for one type of behavior, but also control + click to open a URL associated with the point.

My example to start with that does not have this feature, it just opens the link when you press the points:

from bokeh.models import CustomJS, TapTool, ColumnDataSource
from bokeh.plotting import figure, show

cds = ColumnDataSource({
    'x': [1, 2, 3],
    'y': ['a', 'b', 'c'],
    'link': ['www.google.com', 'www.bing.com', 'www.cnn.com']
})
plot = figure(width=300, height=300, y_range=['a', 'b', 'c'])
plot.scatter(x='x', y='y', color="#fa9fb5", source=cds,
             marker='triangle_pin', size=15)

code = """
window.open('http://'.concat(cb_data.source.data.link[cb_data.source.inspected.indices]), '_blank')
"""
callback = CustomJS(args=dict(), code=code)
tap_tool = TapTool(behavior='inspect', callback=callback)
plot.add_tools(tap_tool)

show(plot)

I want to adjust the callback code to be something like this:

code = """
console.log(window)
console.log(MouseEvent.ctrlKey)
if (MouseEvent.ctrlKey) {
    window.open('http://'.concat(cb_data.source.data.link[cb_data.source.inspected.indices]), '_blank')
} else {
   // do something different
}
"""

Feature description

Create a variable in CustomJS that can communicate the type of click.

Potential alternatives

One potential alternative is a custom extension.

I came up with a workaround that does not use a custom extension, which I am sure is not ideal:

from bokeh.models import CustomJS, TapTool, ColumnDataSource, Tabs, Panel, Div
from bokeh.plotting import figure, show

cds = ColumnDataSource({
    'x': [1, 2, 3],
    'y': ['a', 'b', 'c'],
    'link': ['www.google.com', 'www.bing.com', 'www.cnn.com']
})
plot = figure(width=300, height=300, y_range=['a', 'b', 'c'])
plot.scatter(x='x', y='y', color="#fa9fb5", source=cds, marker='triangle_pin', size=15)

code_1 = """
window.onclick = function () {
    window.ctrl_press = event.ctrlKey || event.metaKey
}
"""
callback_1 = CustomJS(code=code_1)

code_2 = """
if (window.ctrl_press) {
    window.open('http://'.concat(cb_data.source.data.link[cb_data.source.inspected.indices]), '_blank')
}
"""
callback_2 = CustomJS(code=code_2)

tap_tool = TapTool(behavior='inspect', callback=callback_2)
plot.add_tools(tap_tool)

panels = [Panel(child=Div(text='Welcome!'), title='Intro'), Panel(child=plot, title='Example')]
tabs = Tabs(tabs=panels, sizing_mode='stretch_width')
tabs.js_on_change('active', callback_1)

show(tabs)

When the user changes tabs, a callback is set to make a property stored in window equal to whether the control or command key was pressed in the window when a click happens. Now, the TapTool callback has access to this property in window.

Additional information

I am using Bokeh 2.4.2 in the examples.

This is based on the bokeh discourse discussion How to see if user shift clicked or control clicked or command clicked on Tap Tool javascript callback

Thanks in advance!

@bryevdv
Copy link
Member

bryevdv commented Oct 31, 2022

@mattpap IIRC Hammer.js can only support reporting shift and ctrl modifiers, but you are planning on jettisoning hammer in the near future?

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

Successfully merging a pull request may close this issue.

3 participants