from bokeh.plotting import figure, curdoc
from bokeh.models import CustomJS, HoverTool, CheckboxGroup, ColumnDataSource
from bokeh.layouts import gridplot

from collections import OrderedDict

TOOLTIPS = [ ("x", "$~x"), ("y", "$~y") ]

TOOLS = 'crosshair'

data = dict(
    x  = range(10),
    y0 = range(10),
    y1 = range(10)[::-1],
    y2 = [i**0.5 for i in range(10)]
)

source = ColumnDataSource(data=data)

fig = figure(tools=TOOLS)
fig.tools[0].dimensions = 'height'

plots = []
plots.append( fig.line(x='x', y='y0', name="0", source=source) )
plots.append( fig.line(x='x', y='y1', name="1", source=source) )
plots.append( fig.line(x='x', y='y2', name="2", source=source) )


names = ['first','second','third']
checkbox = CheckboxGroup(labels=names, active=[0, 1, 2], width=200)

ID = 0
for plot in plots:
    fig.add_tools(
        HoverTool(
            mode='vline',
            line_policy='interp',
            renderers=[plot],
            names=[str(ID)],
            tooltips=OrderedDict( [('name', names[ID])] + TOOLTIPS ),
            callback=CustomJS(
                args=dict(cb=checkbox),
                code="""
                    if(!cb.active.includes(%d)) {
                        document.getElementsByClassName('bk-tooltip')[%d].style.display = 'none';
                    }
                """ % (ID, ID)
            )
        )
    )
    ID += 1

checkbox.callback = CustomJS(
    args = dict(
        p0 = plots[0],
        p1 = plots[1],
        p2 = plots[2]
    ),
    code = """
        //Toggle glyph visibility based on checkbox status
        p0.visible = cb_obj.active.includes(0);
        p1.visible = cb_obj.active.includes(1);
        p2.visible = cb_obj.active.includes(2);
    """
)

curdoc().add_root(
    gridplot(
        [[fig, checkbox]],
        toolbar_location='left'
    )
)

