But when I publish the webpage with python and use source.js_on_change
, it doesn’t trigger the callback until I’m done with the draw tool. It seems to be there but not sure how to access it in Javascript. Below code using python:
python code:
from bokeh.plotting import figure, output_file, save
from bokeh.models import ColumnDataSource, PointDrawTool, CustomJS
from bokeh.layouts import column
# Create a ColumnDataSource
source = ColumnDataSource(data=dict(x=[1, 2, 3, 4, 5], y=[2, 4, 1, 3, 5]))
# Create the figure
p = figure(width=400, height=400, tools=[])
# Add a circle renderer
renderer = p.circle(x='x', y='y', source=source, size=10, color='blue', alpha=0.5)
lineRenderer =p.line('x', 'y', line_width=2, source=source)
# Create the PointDrawTool and add it to the figure
draw_tool = PointDrawTool(renderers=[renderer])
p.add_tools(draw_tool)
p.toolbar.active_tap = draw_tool
# JavaScript code to sort data
js_code = """
const data = source.data;
const sortedIndices = Array.from(data['x'].keys()).sort((a, b) => data['x'][a] - data['x'][b]);
const sortedX = sortedIndices.map(i => data['x'][i]);
const sortedY = sortedIndices.map(i => data['y'][i]);
source.data = { x: sortedX, y: sortedY };
// update source data
source.change.emit();
console.log('sorted')
"""
# Attach the CustomJS code
custom_js = CustomJS(args=dict(source=source), code=js_code)
source.js_on_change('data', custom_js)
# Save the plot
output_file("point_draw_tool.html")
save(column(p))
And here is the published webapge:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Bokeh Plot</title>
<style>
html, body {
box-sizing: border-box;
display: flow-root;
height: 100%;
margin: 0;
padding: 0;
}
</style>
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-3.2.2.min.js"></script>
<script type="text/javascript">
Bokeh.set_log_level("info");
</script>
</head>
<body>
<div id="dd23e666-af5f-41e7-a42e-28a2e4bc63f3" data-root-id="p1128" style="display: contents;"></div>
<script type="application/json" id="p1129">
{"0fcbebd1-1d00-4cb9-ad1e-31ee57b86f06":{"version":"3.2.2","title":"Bokeh Application","roots":[{"type":"object","name":"Column","id":"p1128","attributes":{"children":[{"type":"object","name":"Figure","id":"p1087","attributes":{"width":400,"height":400,"x_range":{"type":"object","name":"DataRange1d","id":"p1088"},"y_range":{"type":"object","name":"DataRange1d","id":"p1089"},"x_scale":{"type":"object","name":"LinearScale","id":"p1096"},"y_scale":{"type":"object","name":"LinearScale","id":"p1097"},"title":{"type":"object","name":"Title","id":"p1094"},"renderers":[{"type":"object","name":"GlyphRenderer","id":"p1114","attributes":{"data_source":{"type":"object","name":"ColumnDataSource","id":"p1084","attributes":{"js_property_callbacks":{"type":"map","entries":[["change:data",[{"type":"object","name":"CustomJS","id":"p1127","attributes":{"args":{"type":"map","entries":[["source",{"id":"p1084"}]]},"code":"\n const data = source.data;\n const sortedIndices = Array.from(data['x'].keys()).sort((a, b) => data['x'][a] - data['x'][b]);\n const sortedX = sortedIndices.map(i => data['x'][i]);\n const sortedY = sortedIndices.map(i => data['y'][i]);\n source.data = { x: sortedX, y: sortedY };\n\n // update source data\n source.change.emit();\n console.log('sorted')\n"}}]]]},"selected":{"type":"object","name":"Selection","id":"p1085","attributes":{"indices":[],"line_indices":[]}},"selection_policy":{"type":"object","name":"UnionRenderers","id":"p1086"},"data":{"type":"map","entries":[["x",[1,2,3,4,5]],["y",[2,4,1,3,5]]]}}},"view":{"type":"object","name":"CDSView","id":"p1115","attributes":{"filter":{"type":"object","name":"AllIndices","id":"p1116"}}},"glyph":{"type":"object","name":"Circle","id":"p1111","attributes":{"x":{"type":"field","field":"x"},"y":{"type":"field","field":"y"},"size":{"type":"value","value":10},"line_color":{"type":"value","value":"blue"},"line_alpha":{"type":"value","value":0.5},"fill_color":{"type":"value","value":"blue"},"fill_alpha":{"type":"value","value":0.5},"hatch_color":{"type":"value","value":"blue"},"hatch_alpha":{"type":"value","value":0.5}}},"nonselection_glyph":{"type":"object","name":"Circle","id":"p1112","attributes":{"x":{"type":"field","field":"x"},"y":{"type":"field","field":"y"},"size":{"type":"value","value":10},"line_color":{"type":"value","value":"blue"},"line_alpha":{"type":"value","value":0.1},"fill_color":{"type":"value","value":"blue"},"fill_alpha":{"type":"value","value":0.1},"hatch_color":{"type":"value","value":"blue"},"hatch_alpha":{"type":"value","value":0.1}}},"muted_glyph":{"type":"object","name":"Circle","id":"p1113","attributes":{"x":{"type":"field","field":"x"},"y":{"type":"field","field":"y"},"size":{"type":"value","value":10},"line_color":{"type":"value","value":"blue"},"line_alpha":{"type":"value","value":0.2},"fill_color":{"type":"value","value":"blue"},"fill_alpha":{"type":"value","value":0.2},"hatch_color":{"type":"value","value":"blue"},"hatch_alpha":{"type":"value","value":0.2}}}}},{"type":"object","name":"GlyphRenderer","id":"p1123","attributes":{"data_source":{"id":"p1084"},"view":{"type":"object","name":"CDSView","id":"p1124","attributes":{"filter":{"type":"object","name":"AllIndices","id":"p1125"}}},"glyph":{"type":"object","name":"Line","id":"p1120","attributes":{"x":{"type":"field","field":"x"},"y":{"type":"field","field":"y"},"line_color":"#1f77b4","line_width":2}},"nonselection_glyph":{"type":"object","name":"Line","id":"p1121","attributes":{"x":{"type":"field","field":"x"},"y":{"type":"field","field":"y"},"line_color":"#1f77b4","line_alpha":0.1,"line_width":2}},"muted_glyph":{"type":"object","name":"Line","id":"p1122","attributes":{"x":{"type":"field","field":"x"},"y":{"type":"field","field":"y"},"line_color":"#1f77b4","line_alpha":0.2,"line_width":2}}}}],"toolbar":{"type":"object","name":"Toolbar","id":"p1095","attributes":{"tools":[{"type":"object","name":"PointDrawTool","id":"p1126","attributes":{"renderers":[{"id":"p1114"}]}}],"active_tap":{"id":"p1126"}}},"left":[{"type":"object","name":"LinearAxis","id":"p1103","attributes":{"ticker":{"type":"object","name":"BasicTicker","id":"p1104","attributes":{"mantissas":[1,2,5]}},"formatter":{"type":"object","name":"BasicTickFormatter","id":"p1105"},"major_label_policy":{"type":"object","name":"AllLabels","id":"p1106"}}}],"below":[{"type":"object","name":"LinearAxis","id":"p1098","attributes":{"ticker":{"type":"object","name":"BasicTicker","id":"p1099","attributes":{"mantissas":[1,2,5]}},"formatter":{"type":"object","name":"BasicTickFormatter","id":"p1100"},"major_label_policy":{"type":"object","name":"AllLabels","id":"p1101"}}}],"center":[{"type":"object","name":"Grid","id":"p1102","attributes":{"axis":{"id":"p1098"}}},{"type":"object","name":"Grid","id":"p1107","attributes":{"dimension":1,"axis":{"id":"p1103"}}}]}}]}}]}}
</script>
<script type="text/javascript">
(function() {
const fn = function() {
Bokeh.safely(function() {
(function(root) {
function embed_document(root) {
const docs_json = document.getElementById('p1129').textContent;
const render_items = [{"docid":"0fcbebd1-1d00-4cb9-ad1e-31ee57b86f06","roots":{"p1128":"dd23e666-af5f-41e7-a42e-28a2e4bc63f3"},"root_ids":["p1128"]}];
root.Bokeh.embed.embed_items(docs_json, render_items);
}
if (root.Bokeh !== undefined) {
embed_document(root);
} else {
let attempts = 0;
const timer = setInterval(function(root) {
if (root.Bokeh !== undefined) {
clearInterval(timer);
embed_document(root);
} else {
attempts++;
if (attempts > 100) {
clearInterval(timer);
console.log("Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing");
}
}
}, 10, root)
}
})(window);
});
};
if (document.readyState != "loading") fn();
else document.addEventListener("DOMContentLoaded", fn);
})();
</script>
</body>
</html>