TapTool callback not updating CDS

Hi Bryan et al,

I’m trying to get a CustomJS callback in a TapTool to update a ColumnDataSource but it doesn’t seem to be working. Code below. In the browser console log I can see the list of x coordinates being updated when I tap on the line, but the server console readout doesn’t show the same data - the CDS list remains empty. Am I missing something or is this a bug? I’m running v0.12.6 on Ubuntu MATE 16.04.2, Firefox 54.0.

Thanks,
Marcus.

from bokeh.models.sources import ColumnDataSource
from bokeh.models.tools import TapTool
from bokeh.models.callbacks import CustomJS
from bokeh.plotting import Figure
from bokeh.io import curdoc

src = ColumnDataSource(data={‘x’: })

js = ‘’’
var geom = cb_data[‘geometries’];
var data = source.get(‘data’);
var tx = geom[0].x;
var x = data[‘x’];
x.push(tx);
data[‘x’] = x;
source.trigger(‘change’);
console.log(source.get(‘data’)[‘x’]);
‘’’

cjs = CustomJS(args={‘source’: src}, code=js)
tap_tool = TapTool(callback=cjs)

plot = Figure(x_axis_label=‘x’, y_axis_label=‘y’,
plot_width=400, plot_height=400,
x_range=[0, 1], y_range=[0, 1],
tools=[tap_tool])
plot.line([0, 1], [0, 1], line_width=2)

def update():
print(src.data[‘x’])

curdoc().add_root(plot)
curdoc().add_periodic_callback(update, 1000)

I’m still stuck on this - any ideas anyone?

Hi,

Are you expecting the tap tool callback to fire on all mouse taps? It only fires when the tap "hits" glyph and makes a selection. If you want events on arbitrary mouse taps, you would be much better off the recent new bokeh.events module. See, e.g.:

  https://github.com/bokeh/bokeh/blob/master/examples/howto/js_events.py

Or:

  https://github.com/bokeh/bokeh/blob/master/examples/howto/events_app.py

Here is a code snippet from the release blog post that adds new points on every mouse tap:

  from bokeh.events import Tap

  p = figure(x_range=(0,10), y_range=(0,10))
  s1 = ColumnDataSource(data=dict(x=, y=, c=))
  p.circle('x', 'y', size=20, alpha=0.4, source=s1)

  p.js_on_event(Tap, CustomJS(args=dict(s=s1), code="""
                # cb_obj is the "event"
    s.data.x.push(cb_obj.x)
    s.data.y.push(cb_obj.y)
    s.trigger('change')
  """))

Thanks,

Bryan

···

On Jun 27, 2017, at 10:53, Marcus Donnelly <[email protected]> wrote:

I'm still stuck on this - any ideas anyone?

--
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/c8ca0e29-bc99-4c98-a024-4815cb333271%40continuum.io.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.

Hi Bryan,

Thanks for that. I understand that the callback only fires on glpyh selection, but thought it would still work provided I clicked on the line. That said, the bokeh.events module looks like just what I need. However, I tried adapting the code using that - see below - and it still doesn’t work: I can see x and y being appended in the browser console but they remain empty at the python console periodic readout. Perhaps I’m missing something obvious but any help would be appreciated!

Thanks,
Marcus.

from bokeh.models.sources import ColumnDataSource
from bokeh.events import Tap
from bokeh.models.callbacks import CustomJS
from bokeh.plotting import Figure
from bokeh.io import curdoc

src = ColumnDataSource(data={‘x’: , ‘y’: })

js = ‘’’
source.data.x.push(cb_obj.x);
source.data.y.push(cb_obj.y);
source.trigger(‘change’);
console.log(source.data.x)
console.log(source.data.y)
‘’’

cjs = CustomJS(args={‘source’: src}, code=js)

plot = Figure(x_axis_label=‘x’, y_axis_label=‘y’,
plot_width=400, plot_height=400,
x_range=[0, 1], y_range=[0, 1])

plot.circle(‘x’, ‘y’, source=src, size=10, color=‘blue’)
plot.js_on_event(Tap, cjs)

def update():
print(‘x:’, src.data[‘x’], ‘y:’, src.data[‘y’])

curdoc().add_root(plot)
curdoc().add_periodic_callback(update, 1000)

``

Hi Bryan,

I hadn’t looked closely enough at the examples - apologies - working version below. The bokeh.events module is another great addition!

Thanks again for the help,
Marcus.

from bokeh.models.sources import ColumnDataSource
from bokeh.models.callbacks import CustomJS
from bokeh.plotting import Figure
from bokeh.io import curdoc
from bokeh import events

src = ColumnDataSource(data={‘x’: , ‘y’: })

js = ‘’’
source.data.x.push(cb_obj.x);
source.data.y.push(cb_obj.y);
source.trigger(‘change’);
console.log(‘x coords:’, source.data.x);
console.log(‘y coords:’, source.data.y);
‘’’

cjs = CustomJS(args={‘source’: src}, code=js)

plot = Figure(x_axis_label=‘x’, y_axis_label=‘y’,
plot_width=400, plot_height=400,
x_range=[0, 1], y_range=[0, 1])

plot.circle(‘x’, ‘y’, source=src, size=10, color=‘blue’)
plot.js_on_event(events.Tap, cjs)

def update(event):
src.data[‘x’].append(event.x)
src.data[‘y’].append(event.y)
taps = [*zip(src.data[‘x’], src.data[‘y’])]
print(‘Tap locations…’)
for tap in taps:
print(‘x = {x}, y = {y}’.format(x=tap[0], y=tap[1]))

plot.on_event(events.Tap, update)
curdoc().add_root(plot)

``