Repository: bokeh/bokeh

Issue:
CDS callback property not working
This code from Adding Interactions no longer works:
```
from random import random
from bokeh.models import CustomJS, ColumnDataSource
from bokeh.plotting import figure, output_file, show

output_file("callback.html")

x = [random() for x in range(500)]
y = [random() for y in range(500)]
color = ["navy"] * len(x)

s = ColumnDataSource(data=dict(x=x, y=y, color=color))
p = figure(plot_width=400, plot_height=400, tools="lasso_select", title="Select Here")
p.circle('x', 'y', color='color', size=8, source=s, alpha=0.4)

s2 = ColumnDataSource(data=dict(x=[0, 1], ym=[0.5, 0.5]))
p.line(x='x', y='ym', color="orange", line_width=5, alpha=0.6, source=s2)

s.callback = CustomJS(args=dict(s2=s2), code="""
        
        var inds = cb_obj.selected.indices;
        var d = cb_obj.data;
        var ym = 0

        if (inds.length == 0)
            return;

        for (var i = 0; i < d['color'].length; i++) {
            d['color'][i] = "navy"
        }
        for (var i = 0; i < inds.length; i++) {
            d['color'][inds[i]] = "firebrick"
            ym += d['y'][inds[i]]
        }

        ym /= inds.length
        s2.data['ym'] = [ym, ym]

        cb_obj.change.emit();
        s2.change.emit();
    """)

show(p)

```
Although `callback` should be deprecated for 2.0 this should be fixed for now (and also the example updated to use modern code)


Discussion:
modern version: 
```
s.selected.js_on_change('indices', CustomJS(args=dict(s=s, s2=s2), code="""
    const inds = s.selected.indices;
    const d = s.data;
    var ym = 0

    if (inds.length == 0)
        return;

    for (var i = 0; i < d['color'].length; i++) {
        d['color'][i] = "navy"
    }
    for (var i = 0; i < inds.length; i++) {
        d['color'][inds[i]] = "firebrick"
        ym += d['y'][inds[i]]
    }

    ym /= inds.length
    s2.data['ym'] = [ym, ym]

    s.change.emit();
    s2.change.emit();
"""))
```

Resolving patch:
diff --git a/sphinx/source/docs/user_guide/examples/interaction_callbacks_for_selections_lasso_mean.py b/sphinx/source/docs/user_guide/examples/interaction_callbacks_for_selections_lasso_mean.py
--- a/sphinx/source/docs/user_guide/examples/interaction_callbacks_for_selections_lasso_mean.py
+++ b/sphinx/source/docs/user_guide/examples/interaction_callbacks_for_selections_lasso_mean.py
@@ -15,27 +15,27 @@
 s2 = ColumnDataSource(data=dict(x=[0, 1], ym=[0.5, 0.5]))
 p.line(x='x', y='ym', color="orange", line_width=5, alpha=0.6, source=s2)
 
-s.callback = CustomJS(args=dict(s2=s2), code="""
-        var inds = cb_obj.selected.indices;
-        var d = cb_obj.data;
-        var ym = 0
-
-        if (inds.length == 0)
-            return;
-
-        for (var i = 0; i < d['color'].length; i++) {
-            d['color'][i] = "navy"
-        }
-        for (var i = 0; i < inds.length; i++) {
-            d['color'][inds[i]] = "firebrick"
-            ym += d['y'][inds[i]]
-        }
-
-        ym /= inds.length
-        s2.data['ym'] = [ym, ym]
-
-        cb_obj.change.emit();
-        s2.change.emit();
-    """)
+s.selected.js_on_change('indices', CustomJS(args=dict(s=s, s2=s2), code="""
+    const inds = s.selected.indices;
+    const d = s.data;
+    var ym = 0
+
+    if (inds.length == 0)
+        return;
+
+    for (var i = 0; i < d['color'].length; i++) {
+        d['color'][i] = "navy"
+    }
+    for (var i = 0; i < inds.length; i++) {
+        d['color'][inds[i]] = "firebrick"
+        ym += d['y'][inds[i]]
+    }
+
+    ym /= inds.length
+    s2.data['ym'] = [ym, ym]
+
+    s.change.emit();
+    s2.change.emit();
+"""))
 
 show(p)


Test patch:
diff --git a/tests/integration/models/test_sources.py b/tests/integration/models/test_sources.py
--- a/tests/integration/models/test_sources.py
+++ b/tests/integration/models/test_sources.py
@@ -24,8 +24,9 @@
 # Bokeh imports
 from bokeh.layouts import column
 from bokeh.models import (
-    Button, ColumnDataSource, CustomAction, CustomJS, Plot, Range1d,
+    Button, ColumnDataSource, CustomAction, CustomJS, Plot, Range1d, TapTool
 )
+from bokeh.plotting import figure
 from bokeh._testing.util.selenium import RECORD
 
 #-----------------------------------------------------------------------------
@@ -137,3 +138,21 @@ def modify_doc(doc):
 
         # XXX (bev) disabled until https://github.com/bokeh/bokeh/issues/7970 is resolved
         #assert page.has_no_console_errors()
+
+    # XXX callback property to be deprecated for 2.0
+    def test_selection_triggers_callback_property_callback(self, single_plot_page):
+        plot = figure(height=800, width=1000, tools='')
+        r = plot.rect(x=[1, 2], y=[1, 1], width=1, height=1)
+        plot.add_tools(TapTool())
+
+        r.data_source.callback = CustomJS(code=RECORD("indices", "cb_obj.selected.indices"))
+
+        page = single_plot_page(plot)
+
+        page.click_canvas_at_position(400, 500)
+        assert page.results["indices"] == [0]
+
+        page.click_canvas_at_position(600, 300)
+        assert page.results["indices"] == [1]
+
+        assert page.has_no_console_errors()