Execute CustomJS after Button.on_click callback?

Hi,

I have an app which runs a model based on user-controlled settings (via sliders). Since it takes a second to run, I defer re-running the model with the latest settings until the user explicitly clicks a button; with that click I’ve registered a callback function which runs the model and updates the ColumnDataSource which is monitored by a few different plots/figures.

On the same app, I have a fancy little animation/schematic I’ve created purely in the JavaScript world. Alongside that animation are some helper functions that can re-draw the schematic depending on the current output from the model. I can even trigger those helper functions with a CustomJS callback on the button which runs the model. But, here’s the problem - the CustomJS callback runs before in the callback registered with Button.on_click(), so it re-draws the schematic with the last set of output - not the current, new run!

Is there anyway to get my CustomJS callback on the button to run after the click callback? Alternatively, is it possible to register a CustomJS function with any “on_change” function? I was hoping it might be possible to just trigger the CustomJS anytime the ColumnDataSource or a figure drawn on it changes.

Thanks!

  • Daniel

Hi Daniel,

The initial places that CustomJS callbacks were added are all fairly ad-hoc, basically responses to "hey, it would be nice to have a callback option here", as they arose. I'm not sure there is an callback existing callback that would do exactly what you are describing. More broadly, I think it would be good to look at a more general callback system based on named events, that would both decouple having to have explicit callback attributes everywhere as well as potentially be more extensible. But, there's lots of good ideas and only so much human time available.

Since you already seem comfortable using JS, I will offer this as a potential short term workaround: BokehJS models are just Backbone models, so if you want to trigger a callback when a data source changes, there's nothing stopping you to set up standard JS event handlers. I believe something along these lines (untested):

  source.listenTo(source, 'change', my_callback)

or perhaps

  source.on('change', my_callback)

(I'm actually not a great or experienced web-dev, which might explain some BokehJS surprises people run into...) You could set this up in your existing CustomJS callback that fires too early (take care to only do it once), or you could use something like document.get_model_by_name in your other JS code:

  https://github.com/bokeh/bokeh/blob/master/bokehjs/src/coffee/document.coffee#L137

to get the data source you want to trigger off of.

BTW this project sounds pretty neat. If it is public facing, or if you can share a screenshot or testimonial that we could tweet or otherwise feature, please do let us know. (I know that's often not the case, though) An issue with OSS development is that it is performed by human beings, who can very easily be subject to skewed perspectives. :slight_smile: Basically the only side of things I see most days is the "this has a problem" or "that doesn't work" side, so affirmative examples of success stories are an extremely welcome and valuable motivators.

Thanks,

Bryan

···

On Mar 3, 2016, at 8:00 AM, [email protected] wrote:

Hi,

I have an app which runs a model based on user-controlled settings (via sliders). Since it takes a second to run, I defer re-running the model with the latest settings until the user explicitly clicks a button; with that click I've registered a callback function which runs the model and updates the ColumnDataSource which is monitored by a few different plots/figures.

On the same app, I have a fancy little animation/schematic I've created purely in the JavaScript world. Alongside that animation are some helper functions that can re-draw the schematic depending on the current output from the model. I can even trigger those helper functions with a CustomJS callback on the button which runs the model. But, here's the problem - the CustomJS callback runs before in the callback registered with Button.on_click(), so it re-draws the schematic with the last set of output - not the current, new run!

Is there anyway to get my CustomJS callback on the button to run after the click callback? Alternatively, is it possible to register a CustomJS function with any "on_change" function? I was hoping it might be possible to just trigger the CustomJS anytime the ColumnDataSource or a figure drawn on it changes.

Thanks!
- Daniel

--
You received this message because you are subscribed to the Google Groups "Bokeh Discussion - Public" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/4078df77-5414-4416-9739-4d1cd65b0343%40continuum.io.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.

Hi Bryan -

Thanks, I’ll take a look into this approach later this afternoon.

Honestly, I’m overselling how fancy the project is - it’s a user interface for a very simple box model that we’re providing to participants in a High School-level science oceanography/science competition at MIT this weekend. The schematic I’m drawing updates to reflect some simple changes in the model - whether or not tides are on, river discharge, etc. Once all is said and done I’d be happy to make my git repo public and provide a testimonial; we plan on giving a talk on the project at an ocean sciences education conference later this year anyway, so I can link that as well once it’s done. The app is supposed to have some other cool little drawings, too - scaling arrows showing the relative strengths of sources/sinks, fishes swimming (or dying, depending on the boundary conditions they set for the model), etc - pending today’s work and my totally hackish SVG skills. The students may need to use their imagination when it comes to evaluating whether there is a fish kill or not… still, it’s leaps and bounds better than having them scratch out things on the back of an envelope!

Will keep you all updated with the results! Bokeh really did end up being a fantastic tool for this project - it made it super simple to get a “proof of concept” up and running, and that totally blew some of my collaborators away.

  • Daniel
···

On Thursday, March 3, 2016 at 9:42:14 AM UTC-5, Bryan Van de ven wrote:

Hi Daniel,

The initial places that CustomJS callbacks were added are all fairly ad-hoc, basically responses to “hey, it would be nice to have a callback option here”, as they arose. I’m not sure there is an callback existing callback that would do exactly what you are describing. More broadly, I think it would be good to look at a more general callback system based on named events, that would both decouple having to have explicit callback attributes everywhere as well as potentially be more extensible. But, there’s lots of good ideas and only so much human time available.

Since you already seem comfortable using JS, I will offer this as a potential short term workaround: BokehJS models are just Backbone models, so if you want to trigger a callback when a data source changes, there’s nothing stopping you to set up standard JS event handlers. I believe something along these lines (untested):

    source.listenTo(source, 'change', my_callback)

or perhaps

    source.on('change', my_callback)

(I’m actually not a great or experienced web-dev, which might explain some BokehJS surprises people run into…) You could set this up in your existing CustomJS callback that fires too early (take care to only do it once), or you could use something like document.get_model_by_name in your other JS code:

    [https://github.com/bokeh/bokeh/blob/master/bokehjs/src/coffee/document.coffee#L137](https://github.com/bokeh/bokeh/blob/master/bokehjs/src/coffee/document.coffee#L137)

to get the data source you want to trigger off of.

BTW this project sounds pretty neat. If it is public facing, or if you can share a screenshot or testimonial that we could tweet or otherwise feature, please do let us know. (I know that’s often not the case, though) An issue with OSS development is that it is performed by human beings, who can very easily be subject to skewed perspectives. :slight_smile: Basically the only side of things I see most days is the “this has a problem” or “that doesn’t work” side, so affirmative examples of success stories are an extremely welcome and valuable motivators.

Thanks,

Bryan

On Mar 3, 2016, at 8:00 AM, [email protected] wrote:

Hi,

I have an app which runs a model based on user-controlled settings (via sliders). Since it takes a second to run, I defer re-running the model with the latest settings until the user explicitly clicks a button; with that click I’ve registered a callback function which runs the model and updates the ColumnDataSource which is monitored by a few different plots/figures.

On the same app, I have a fancy little animation/schematic I’ve created purely in the JavaScript world. Alongside that animation are some helper functions that can re-draw the schematic depending on the current output from the model. I can even trigger those helper functions with a CustomJS callback on the button which runs the model. But, here’s the problem - the CustomJS callback runs before in the callback registered with Button.on_click(), so it re-draws the schematic with the last set of output - not the current, new run!

Is there anyway to get my CustomJS callback on the button to run after the click callback? Alternatively, is it possible to register a CustomJS function with any “on_change” function? I was hoping it might be possible to just trigger the CustomJS anytime the ColumnDataSource or a figure drawn on it changes.

Thanks!

  • Daniel


You received this message because you are subscribed to the Google Groups “Bokeh Discussion - Public” group.

To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].

To post to this group, send email to [email protected].

To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/4078df77-5414-4416-9739-4d1cd65b0343%40continuum.io.

For more options, visit https://groups.google.com/a/continuum.io/d/optout.

Daniel,

Awesome! Please let me know if this approach works, if not I will try to think if there is another route. If all else fails, adding another ad-hoc customJS property on data sources would be a quick PR for the very short term, until a more general events system can be worked on.

Bryan

···

On Mar 3, 2016, at 8:58 AM, [email protected] wrote:

Hi Bryan -

Thanks, I'll take a look into this approach later this afternoon.

Honestly, I'm overselling how fancy the project is - it's a user interface for a very simple box model that we're providing to participants in a High School-level science oceanography/science competition at MIT this weekend. The schematic I'm drawing updates to reflect some simple changes in the model - whether or not tides are on, river discharge, etc. Once all is said and done I'd be happy to make my git repo public and provide a testimonial; we plan on giving a talk on the project at an ocean sciences education conference later this year anyway, so I can link that as well once it's done. The app is supposed to have some other cool little drawings, too - scaling arrows showing the relative strengths of sources/sinks, fishes swimming (or dying, depending on the boundary conditions they set for the model), etc - pending today's work and my totally hackish SVG skills. The students may need to use their imagination when it comes to evaluating whether there is a fish kill or not... still, it's leaps and bounds better than having them scratch out things on the back of an envelope!

Will keep you all updated with the results! Bokeh really did end up being a fantastic tool for this project - it made it super simple to get a "proof of concept" up and running, and that totally blew some of my collaborators away.

- Daniel

On Thursday, March 3, 2016 at 9:42:14 AM UTC-5, Bryan Van de ven wrote:
Hi Daniel,

The initial places that CustomJS callbacks were added are all fairly ad-hoc, basically responses to "hey, it would be nice to have a callback option here", as they arose. I'm not sure there is an callback existing callback that would do exactly what you are describing. More broadly, I think it would be good to look at a more general callback system based on named events, that would both decouple having to have explicit callback attributes everywhere as well as potentially be more extensible. But, there's lots of good ideas and only so much human time available.

Since you already seem comfortable using JS, I will offer this as a potential short term workaround: BokehJS models are just Backbone models, so if you want to trigger a callback when a data source changes, there's nothing stopping you to set up standard JS event handlers. I believe something along these lines (untested):

        source.listenTo(source, 'change', my_callback)

or perhaps

        source.on('change', my_callback)

(I'm actually not a great or experienced web-dev, which might explain some BokehJS surprises people run into...) You could set this up in your existing CustomJS callback that fires too early (take care to only do it once), or you could use something like document.get_model_by_name in your other JS code:

        https://github.com/bokeh/bokeh/blob/master/bokehjs/src/coffee/document.coffee#L137

to get the data source you want to trigger off of.

BTW this project sounds pretty neat. If it is public facing, or if you can share a screenshot or testimonial that we could tweet or otherwise feature, please do let us know. (I know that's often not the case, though) An issue with OSS development is that it is performed by human beings, who can very easily be subject to skewed perspectives. :slight_smile: Basically the only side of things I see most days is the "this has a problem" or "that doesn't work" side, so affirmative examples of success stories are an extremely welcome and valuable motivators.

Thanks,

Bryan

> On Mar 3, 2016, at 8:00 AM, [email protected] wrote:
>
> Hi,
>
> I have an app which runs a model based on user-controlled settings (via sliders). Since it takes a second to run, I defer re-running the model with the latest settings until the user explicitly clicks a button; with that click I've registered a callback function which runs the model and updates the ColumnDataSource which is monitored by a few different plots/figures.
>
> On the same app, I have a fancy little animation/schematic I've created purely in the JavaScript world. Alongside that animation are some helper functions that can re-draw the schematic depending on the current output from the model. I can even trigger those helper functions with a CustomJS callback on the button which runs the model. But, here's the problem - the CustomJS callback runs before in the callback registered with Button.on_click(), so it re-draws the schematic with the last set of output - not the current, new run!
>
> Is there anyway to get my CustomJS callback on the button to run after the click callback? Alternatively, is it possible to register a CustomJS function with any "on_change" function? I was hoping it might be possible to just trigger the CustomJS anytime the ColumnDataSource or a figure drawn on it changes.
>
> Thanks!
> - Daniel
>
> --
> You received this message because you are subscribed to the Google Groups "Bokeh Discussion - Public" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
> To post to this group, send email to [email protected].
> To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/4078df77-5414-4416-9739-4d1cd65b0343%40continuum.io.
> For more options, visit https://groups.google.com/a/continuum.io/d/optout.

--
You received this message because you are subscribed to the Google Groups "Bokeh Discussion - Public" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/0e054f1d-4882-422a-8564-39744a7cfdc9%40continuum.io.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.