Skillversitas

Developing with JavaScript (CustomJS)

When you need behavior that Bokeh's Python callbacks don't cover - or you want logic to run entirely in the browser - you embed JavaScript. CustomJS is the model for client-side callbacks: you pass a JS string that receives the Bokeh document and the event, and it manipulates the plot's JS-side state directly.

CustomJS Basics

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

p = figure()
p.circle([1, 2, 3], [1, 2, 3])

js = '''
    var circles = cb_obj.ownerDocument.select_one("circle").data;
    circles.x = [3, 2, 1];
    circles.y = [3, 2, 1];
    cb_obj.ownerDocument.invalidate();
'''
btn = Button(label="Flip", js_on_change={"click": CustomJS(code=js)})

Passing Python Values into JS

from bokeh.models import CustomJS, Slider

slider = Slider(start=0, end=10, value=5)
js = '''
    var threshold = args.threshold;
    var src = cb_obj.ownerDocument.get_model_by_id(args.src_id);
    // filter src.data based on threshold ...
'''
slider.js_on_change("value", CustomJS(args={"threshold": 5, "src_id": "..."},
                                      code=js))

args maps Python values (or model references) into the JS scope as args.name.

js_on_change on Any Model

from bokeh.models import CustomJS

source.js_on_change("data", CustomJS(code='''
    console.log("data changed", cb_obj.data);
'''))

When to Reach for JS

  • Client-only logic that must run without a server (static HTML exports).
  • Accessing browser APIs (localStorage, fetch to your own backend).
  • Complex visual effects or DOM manipulation Bokeh models don't expose.
  • Keep it minimal: prefer Python callbacks and Bokeh models when possible - they are easier to maintain and work in server apps.

Summary

Embed JavaScript in Bokeh with CustomJS: attach it via js_on_change or js_on_click, receive the event through cb_obj, reach the document and models via cb_obj.ownerDocument, and pass Python values through the args dict. Use JS for browser-only behavior and custom effects; prefer Python callbacks and data models for everything else.