Taptool does not work as it used to in 0.11.1

Hi all,

I have widgets that perform some action based upon what glyph is selected by the taptool. The way this had been done was to set a variable in a column data source with the name of the selected glyph in the JS callback for the taptool. If the plot background was selected the taptool used to still register this as an event and would allow for the variable to be set as ‘None’. However this does not seem to be the case anymore as the taptool does not activate when something other than one of the glyphs it is associated with is tapped. Visually the glyphs are deselected but I can’t seem to figure out a way access that data determining which are selected or not. I’ve included some example code that shows the method that worked in Bokeh version 0.11.1 as a sort of workaround for determining selected or deselected glyphs. I am currently using Bokeh version 0.12.2.

from bokeh.plotting import figure
from bokeh.models import ColumnDataSource, TapTool
from bokeh.models.widgets import Button
from bokeh.layouts import column

//source contains information for the glyph positions and their names
source = ColumnDataSource(data=dict(x=[1,3,5,7,9], y=[2,4,6,8,10], names=[a,b,c,d,e]))
//selected is the CDS that holds which glyph is selected
selected = ColumnDataSource(data=dict(selected=‘None’))

taptooljs = “”"
var source = cb_obj.get(‘data’);
//I want to get the name of the circle that was selected
var ind = cb_obj.get(‘selected’)[‘1d’].indices;
var name = source[‘names’][ind];
var qc = typeof(name);

        //if a circle was not selected name would be a non-string type and
        //the selected CDS could be updated with the info that 'None' is selected
        if(qc != 'string'){
            selected.get('data')['selected'] = 'None';
            selected.trigger('change');
            return;
        }
       
        selected.get('data')['selected'] = name;
        selected.trigger('change');
        """

button_js = “”"
//this just alerts the page with the currently selected circle
var name = selected.get(‘data’)[‘selected’];
alert(name);
“”"

plot = figure()
circ = plot.circle(‘x’, ‘y’, color=‘red’, size=10, source=source)
circ.selection_glyph = Circle(fill_alpha=1, fill_color=‘green’, line_color=None)
circ.nonselection_glyph = Circle(fill_alpha=0.5, fill_color=‘red’, line_color=None)

tap = TapTool(renderers=[circ], callback=CustomJS(args=dict(selected=selected), code=taptooljs))
button = Button(label=‘Show Name’, callback=CustomJS(args=dict(selected=selected), code=button_js))

plot.add_tools(tap)

layout = column(plot, button)

output_file = (‘taptool_test.html’, title=‘taptool test’)

show(layout)

The way that this should work is that the button should display the name of the selected glyph, and if no glyph is selected or if the glyphs are deselected by tapping the background the button should display ‘None’. Currently if the glyphs are deselected they are visually correct but pressing the button will show that the last selected glyph is still selected in the column data source.

Hi, your code is not runnable as-is. After fixing four different small problems (syntax errors, things that were supposed to be strings, not variables, etc), there was still an error. Unfortunately, I don't have time to debugging things that aren't even the actual issue at hand. If you can post a new complete, minimal, *runnable* example then I or someone else can possibly take a closer look.

Thanks,

Bryan

[bryan:/tmp] \[bryan:/tmp\] python foo.py
  File "foo.py", line 6
    //source contains information for the glyph positions and their names
     ^
SyntaxError: invalid syntax
[bryan:/tmp] python foo\.py   File "foo\.py", line 48     output\_file = \('taptool\_test\.html', title='taptool test'\)                                              ^ SyntaxError: invalid syntax \[bryan:/tmp\] python foo.py
Traceback (most recent call last):
  File "foo.py", line 7, in <module>
    source = ColumnDataSource(data=dict(x=[1,3,5,7,9], y=[2,4,6,8,10], names=[a,b,c,d,e]))
NameError: name 'a' is not defined
[bryan:/tmp] python foo\.py Traceback \(most recent call last\): &nbsp;&nbsp;File &quot;foo\.py&quot;, line 9, in &lt;module&gt; &nbsp;&nbsp;&nbsp;&nbsp;selected = ColumnDataSource\(data=dict\(selected=&#39;None&#39;\)\) &nbsp;&nbsp;File &quot;/Users/bryan/work/bokeh/bokeh/models/sources\.py&quot;, line 90, in \_\_init\_\_ &nbsp;&nbsp;&nbsp;&nbsp;self\.add\(data, name\) &nbsp;&nbsp;File &quot;/Users/bryan/work/bokeh/bokeh/models/sources\.py&quot;, line 166, in add &nbsp;&nbsp;&nbsp;&nbsp;self\.data\[name\] = data &nbsp;&nbsp;File &quot;/Users/bryan/work/bokeh/bokeh/core/property\_containers\.py&quot;, line 19, in wrapper &nbsp;&nbsp;&nbsp;&nbsp;self\.\_notify\_owners\(old\) &nbsp;&nbsp;File &quot;/Users/bryan/work/bokeh/bokeh/core/property\_containers\.py&quot;, line 44, in \_notify\_owners &nbsp;&nbsp;&nbsp;&nbsp;prop\.\_notify\_mutated\(owner, old, hint\) &nbsp;&nbsp;File &quot;/Users/bryan/work/bokeh/bokeh/core/properties\.py&quot;, line 474, in \_notify\_mutated &nbsp;&nbsp;&nbsp;&nbsp;value = self\.descriptor\.prepare\_value\(obj\.\_\_class\_\_, self\.name, value\) &nbsp;&nbsp;File &quot;/Users/bryan/work/bokeh/bokeh/core/properties\.py&quot;, line 276, in prepare\_value &nbsp;&nbsp;&nbsp;&nbsp;raise e &nbsp;&nbsp;File &quot;/Users/bryan/work/bokeh/bokeh/core/properties\.py&quot;, line 269, in prepare\_value &nbsp;&nbsp;&nbsp;&nbsp;self\.validate\(value\) &nbsp;&nbsp;File &quot;/Users/bryan/work/bokeh/bokeh/core/properties\.py&quot;, line 1198, in validate &nbsp;&nbsp;&nbsp;&nbsp;raise ValueError\(&quot;expected an element of %s, got %r&quot; % \(self, value\)\) ValueError: expected an element of Dict\(String, Seq\(Any\)\), got \{&#39;selected&#39;: &#39;None&#39;\} \[bryan:/tmp\]

···

On Oct 14, 2016, at 11:02 AM, [email protected] wrote:

Hi all,

I have widgets that perform some action based upon what glyph is selected by the taptool. The way this had been done was to set a variable in a column data source with the name of the selected glyph in the JS callback for the taptool. If the plot background was selected the taptool used to still register this as an event and would allow for the variable to be set as 'None'. However this does not seem to be the case anymore as the taptool does not activate when something other than one of the glyphs it is associated with is tapped. Visually the glyphs are deselected but I can't seem to figure out a way access that data determining which are selected or not. I've included some example code that shows the method that worked in Bokeh version 0.11.1 as a sort of workaround for determining selected or deselected glyphs. I am currently using Bokeh version 0.12.2.

from bokeh.plotting import figure
from bokeh.models import ColumnDataSource, TapTool
from bokeh.models.widgets import Button
from bokeh.layouts import column

//source contains information for the glyph positions and their names
source = ColumnDataSource(data=dict(x=[1,3,5,7,9], y=[2,4,6,8,10], names=[a,b,c,d,e]))
//selected is the CDS that holds which glyph is selected
selected = ColumnDataSource(data=dict(selected='None'))

taptooljs = """
            var source = cb_obj.get('data');
            //I want to get the name of the circle that was selected
            var ind = cb_obj.get('selected')['1d'].indices;
            var name = source['names'][ind];
            var qc = typeof(name);
            
            //if a circle was not selected name would be a non-string type and
            //the selected CDS could be updated with the info that 'None' is selected
            if(qc != 'string'){
                selected.get('data')['selected'] = 'None';
                selected.trigger('change');
                return;
            }
            
            selected.get('data')['selected'] = name;
            selected.trigger('change');
            """

button_js = """
            //this just alerts the page with the currently selected circle
            var name = selected.get('data')['selected'];
            alert(name);
            """

plot = figure()
circ = plot.circle('x', 'y', color='red', size=10, source=source)
circ.selection_glyph = Circle(fill_alpha=1, fill_color='green', line_color=None)
circ.nonselection_glyph = Circle(fill_alpha=0.5, fill_color='red', line_color=None)
     
tap = TapTool(renderers=[circ], callback=CustomJS(args=dict(selected=selected), code=taptooljs))
button = Button(label='Show Name', callback=CustomJS(args=dict(selected=selected), code=button_js))

plot.add_tools(tap)

layout = column(plot, button)

output_file = ('taptool_test.html', title='taptool test')

show(layout)

The way that this should work is that the button should display the name of the selected glyph, and if no glyph is selected or if the glyphs are deselected by tapping the background the button should display 'None'. Currently if the glyphs are deselected they are visually correct but pressing the button will show that the last selected glyph is still selected in the column data source.

--
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/92d16887-f149-4dd8-a16f-8a48183d5e70%40continuum.io.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.