My solution for this is to use the original data (x in your case) for recalculating the histogram within the customjs. I am really new to javascript so there may be more elegant way to implement this. But the code works for me anyway so you can give it a try.
import pandas as pd
import numpy as np
from bokeh.plotting import figure
from bokeh.models.widgets import Slider, RangeSlider
from bokeh.models import ColumnDataSource, CustomJS
# generate random data
x = np.random.normal(10, 1, 1000)
# generate histogram
hist, edges = np.histogram(x, bins = 10)
# create dataframe of histogram
hist_df = pd.DataFrame({'count': hist, 'left':edges[:-1], 'right':edges[1:]})
# generate bokeh data source for initial histogram
bokeh_data = ColumnDataSource(hist_df)
# generate bokeh data source for new histogram calculation
x_df=pd.DataFrame(x,columns={'value'})
x_src=ColumnDataSource(x_df)
# generate bokeh plot
plot = figure()
plot.quad(source = bokeh_data, bottom = 0, top = 'count', left = 'left', right = 'right')
callback = CustomJS(args=dict(source1=x_src,source2=bokeh_data), code="""
var data = source1.data;
var val = data['value'];
var length = val.length;
var size = bin_size.value;
var min = data_range.value[0];
var max = data_range.value[1];
// Decide number of bins needed
var bins = Math.floor((max - min) / size);
// Put left edge point in an array
var left_edge = new Array(bins);
for (var i = 0; i < bins; i++){
left_edge[i] = min+i*size;
}
// Put right edge point in an array
var right_edge = new Array(bins);
for (var i = 0; i < bins; i++){
right_edge[i] = min+(i+1)*size;
}
// Initialize frequency
var frequency = new Array(bins);
for (var i = 0; i < bins; i++) frequency[i] = 0;
// Calculate frequency for each bin
for (var i = 0; i < length; i++) {
if (val[i]==min) frequency[0]++;
else if (val[i]==max) frequency[bins-1]++;
else frequency[Math.floor((val[i] - min) / size)]++;
}
// Oupdate data source with new bins and frequency
var bokeh_data_new={};
bokeh_data_new.count=frequency;
bokeh_data_new.left=left_edge;
bokeh_data_new.right=right_edge;
source2.data=bokeh_data_new;
""")
# generate slider object to change bin widths interactively
binwidth_slider = Slider(start = 0, end = 1, step = 0.02, value = 0.5 , callback=callback)
callback.args["bin_size"] = binwidth_slider
# generate range slider object to change min and max of the data points to be shown interactively
range_slider = RangeSlider(start = 0, end = 20, step = 1, value = (0, 20), callback=callback)
callback.args["data_range"] = range_slider
widgets = WidgetBox(binwidth_slider, range_slider)
output_notebook()
show(row(plot, widgets))