Utilizing Page Visibility API

I have Django app with a plot that is showing the current CPU/RAM usage. This script makes a GET call every second to retrieve information gathered by Celery. I am trying to add an clearInterval() call everytime the tab with the app is hidden to minimize the ammount of GETs.

I have tried to add a js_on_event call to the source but it does nothing (i don’t even get the console logs). Adding the custom JS to html page works, but I dont have reference to the plot objects (source).


source = AjaxDataSource(
        # Initial data provided to make axes generate properly at the start.
source.js_on_event('document_visibilitychange', CustomJS(
        args={'periodSelect': variable_for_selectWidget},

js_on_event CustomJS

document.addEventListener('visibilitychange', function () {
    if (document.hidden) {
    } else {
        var intervalMap = {
            'minute': 1000,
            'hour': 1000*60,
            'day': null,
            'month': null
        this.period = periodSelect.value;
        this.data_url = `/path/to/ask/?period=${this.period}`;
        this.polling_interval = intervalMap[periodSelect.value];
        const callback = () => this.get_data(this.mode, this.max_size, this.if_modified);
        if (this.polling_interval != null) {
            this.interval = setInterval(callback, this.polling_interval);

I have also tried the code without the document.addEventListener('visibilitychange', function () { part
There are a number of on_change events added to tools, but as the name implies, they are on change and two of them refer to the source

It’s not completely ideal, but one avenue to connect non-Bokeh callbacks to Bokeh objects is to configure the name property on the Bokeh object you want to manipulate it, then you can grab ahold of it in “outside” code with


(assuming there is only one document on a page which is fairly typical)

@carolyn is interested in helping to figure out some better paths in the future for this as well.


well… I got 33 documents soo… it might be quite tedious to find the right one :frowning:

I found the right one. Now gonna fight with a different problem, but this really helped for now :slight_smile: It is a partial solution but will mark it as one!

Thank you @Bryan!

Please do continue the discussion with @carolyn on a new GitHub issue, this is exactly the sort of use case that we’d like find ways to improve.

@Bryan - I created an issue