js_on_event (original) (raw)

Demonstration of how to register event callbacks using an adaptation of the color_scatter example from the bokeh gallery

from future import annotations

import numpy as np

from bokeh import events from bokeh.io import curdoc, show from bokeh.layouts import column, row from bokeh.models import Button, CustomJS, Div, TextInput from bokeh.plotting import figure

def display_event(div: Div, attributes: list[str] = []) -> CustomJS: """ Function to build a suitable CustomJS to display the current event in the div model. """ style = 'float: left; clear: left; font-size: 13px' return CustomJS(args=dict(div=div), code=f""" const attrs = {attributes}; const args = []; for (let i = 0; i < attrs.length; i++) {{ const val = JSON.stringify(cb_obj[attrs[i]], function(key, val) {{ return val.toFixed ? Number(val.toFixed(2)) : val; }}) args.push(attrs[i] + '=' + val) }} const line = "" + cb_obj.event_name + "(" + args.join(", ") + ")\n"; const text = div.text.concat(line); const lines = text.split("\n") if (lines.length > 35) lines.shift(); div.text = lines.join("\n"); """)

N = 4000 x = np.random.random(size=N) * 100 y = np.random.random(size=N) * 100 radii = np.random.random(size=N) * 1.5 colors = np.array([(r, g, 150) for r, g in zip(50+2x, 30+2y)], dtype="uint8")

p = figure(tools="pan,wheel_zoom,zoom_in,zoom_out,reset,tap,lasso_select,box_select,box_zoom,undo,redo")

p.circle(x, y, radius=radii, fill_color=colors, fill_alpha=0.6, line_color=None)

Add a div to display events and a button to trigger button click events

div = Div(width=1000) button = Button(label="Button", button_type="success", width=300) text_input = TextInput(placeholder="Input a value and press Enter ...", width=300) layout = column(button, text_input, row(p, div))

Register event callbacks

Button events

button.js_on_event(events.ButtonClick, display_event(div))

TextInput events

text_input.js_on_event(events.ValueSubmit, display_event(div, ["value"]))

AxisClick events

p.xaxis[0].js_on_event(events.AxisClick, display_event(div, ["value"])) p.yaxis[0].js_on_event(events.AxisClick, display_event(div, ["value"]))

LOD events

p.js_on_event(events.LODStart, display_event(div)) p.js_on_event(events.LODEnd, display_event(div))

Point events

point_attributes = ['x','y','sx','sy'] p.js_on_event(events.Tap, display_event(div, attributes=point_attributes)) p.js_on_event(events.DoubleTap, display_event(div, attributes=point_attributes)) p.js_on_event(events.Press, display_event(div, attributes=point_attributes)) p.js_on_event(events.PressUp, display_event(div, attributes=point_attributes))

Mouse wheel event

p.js_on_event(events.MouseWheel, display_event(div,attributes=[*point_attributes, 'delta']))

Mouse move, enter and leave

p.js_on_event(events.MouseMove, display_event(div, attributes=point_attributes))

p.js_on_event(events.MouseEnter, display_event(div, attributes=point_attributes)) p.js_on_event(events.MouseLeave, display_event(div, attributes=point_attributes))

Pan events

pan_attributes = [*point_attributes, 'delta_x', 'delta_y'] p.js_on_event(events.Pan, display_event(div, attributes=pan_attributes)) p.js_on_event(events.PanStart, display_event(div, attributes=point_attributes)) p.js_on_event(events.PanEnd, display_event(div, attributes=point_attributes))

Pinch events

pinch_attributes = [*point_attributes, 'scale'] p.js_on_event(events.Pinch, display_event(div, attributes=pinch_attributes)) p.js_on_event(events.PinchStart, display_event(div, attributes=point_attributes)) p.js_on_event(events.PinchEnd, display_event(div, attributes=point_attributes))

Ranges Update events

p.js_on_event(events.RangesUpdate, display_event(div, attributes=['x0','x1','y0','y1']))

Selection events

p.js_on_event(events.SelectionGeometry, display_event(div, attributes=['geometry', 'final']))

curdoc().on_event(events.DocumentReady, display_event(div))

show(layout)