7

I have a Bokeh application that makes use of the Python callbacks for various widget events. With certain events, I'd like to execute some JavaScript code before making the callback to the Python function. Is this possible?

In this case, the Python callback is potentially long-running, and I'd like to start and stop a Javascript spinner object before and after the long-running Python code executes.

tbc
  • 1,679
  • 3
  • 21
  • 28

1 Answers1

8

As of Bokeh 1.0.4, "busy" / "done" events (to enable things like triggering spinners or other UI events) are still an open feature request.

In the mean time, your best bet is to use some "dummy" model to trigger a CustomJS callback. For instance, you could add an invisible glyph, and trigger a CustomJS any property on it as a proxy for a "busy" event. This is clunky, but serviceable.

Here is a very rough outline example. The first alert will pop up immediately. Close it, the next alert will pop up 5 seconds later.

import time

from bokeh.io import curdoc
from bokeh.layouts import column
from bokeh.models import Button, CustomJS
from bokeh.plotting import figure

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

dummy = p.circle([1], [2], alpha=0)
dummy.glyph.js_on_change('size', CustomJS(code="""
alert(cb_obj.size.value)
"""))

b = Button()
def cb():
    dummy.glyph.size = 10
    time.sleep(5)
    dummy.glyph.size = 20

b.on_click(cb)

curdoc().add_root(column(b, p))
bigreddot
  • 33,642
  • 5
  • 69
  • 122
  • I am not sure how to connect an event (i.e. button click) to both my python callback and a property change on the "dummy" model instance? If the python callback changes the property, then the client side won't see that change until the callback completes (which would be good for stopping my spinner). But I am not sure how handle/capture the starting event. – tbc May 30 '17 at 18:43
  • "If the python callback changes the property, then the client side won't see that change until the callback completes" That's not true, see the example code in the updated answer. – bigreddot May 30 '17 at 20:22
  • So what is the mechanism that allows this to work? I was (obviously) assuming that a request would go from client to server to execute the python callback and that not data would "emit" from the python callback until that function returned - and the data was transferred back over the network to the client. What allows data to come from server back to the client before the python callback returns? – tbc May 31 '17 at 15:48
  • All changes to properties are currently detected immediately, and the corresponding protocol message for patching Bokeh documents with updated properties are also sent across the websocket immediately. There is an open issue somewhere to support a "batch" mode to defer updates until some later time, but there has not been much user demand around it so it has not been prioritized. – bigreddot May 31 '17 at 17:32