Javascript 引用Bokeh数据表中的行/列的JS代码出错

Javascript 引用Bokeh数据表中的行/列的JS代码出错,javascript,charts,bokeh,Javascript,Charts,Bokeh,我使用了前面的文章,并尝试运行代码,通过这些代码,我可以在Bokeh的DataTable中选择一行,并获取行号。然而,我发现使用该代码,一旦我通过第6行或第7行,生成的行号是错误的-例如,我可以单击第17行,它会说是第6行。我如何解决这个问题 注意:对于post中的代码,只有当我将“source”列DataSource中的范围从10增加到20时,才会发生错误 from random import randint from datetime import date from bokeh.model

我使用了前面的文章,并尝试运行代码,通过这些代码,我可以在Bokeh的DataTable中选择一行,并获取行号。然而,我发现使用该代码,一旦我通过第6行或第7行,生成的行号是错误的-例如,我可以单击第17行,它会说是第6行。我如何解决这个问题

注意:对于post中的代码,只有当我将“source”列DataSource中的范围从10增加到20时,才会发生错误

from random import randint
from datetime import date
from bokeh.models import ColumnDataSource, TableColumn, DateFormatter, DataTable, CustomJS
from bokeh.layouts import column
from bokeh.models.widgets import TextInput
from bokeh.plotting import curdoc

source = ColumnDataSource(dict(dates = [date(2014, 3, i + 1) for i in range(20)], downloads = [randint(0, 100) for i in range(20)]))
columns = [TableColumn(field = "dates", title = "Date", formatter = DateFormatter()), TableColumn(field = "downloads", title = "Downloads")]
data_table = DataTable(source = source, columns = columns, width = 400, height = 280, editable = True, reorderable = False)

text_row = TextInput(value = None, title = "Row index:", width = 420)
text_column = TextInput(value = None, title = "Column Index:", width = 420)
text_date = TextInput(value = None, title = "Date:", width = 420)
text_downloads = TextInput(value = None, title = "Downloads:", width = 420)
test_cell = TextInput(value = None, title = "Cell Contents:", width = 420)

source_code = """
var grid = document.getElementsByClassName('grid-canvas')[0].children;
var row, column = '';

for (var i = 0,max = grid.length; i < max; i++){
    if (grid[i].outerHTML.includes('active')){
        row = i;
        for (var j = 0, jmax = grid[i].children.length; j < jmax; j++)
            if(grid[i].children[j].outerHTML.includes('active')) 
                { column = j }
    }
}
text_row.value = String(row);
text_column.value = String(column);
text_date.value = String(new Date(source.data['dates'][row]));
text_downloads.value = String(source.data['downloads'][row]); 
test_cell.value = column == 1 ? text_date.value : text_downloads.value; """

def py_callback(attr, old, new):
    print(test_cell.value)
    print(text_date.value)
    source.selected.update(indices = [])

source.selected.on_change('indices', py_callback)
callback = CustomJS(args = dict(source = source, text_row = text_row, text_column = text_column, text_date = text_date, text_downloads = text_downloads, test_cell = test_cell), code = source_code)
source.selected.js_on_change('indices', callback)
curdoc().add_root(column(data_table, text_row, text_column, text_date, text_downloads, test_cell))
来自随机导入randint
起始日期时间导入日期
从bokeh.models导入ColumnDataSource、TableColumn、DateFormatter、DataTable、CustomJS
从bokeh.layouts导入列
从bokeh.models.widgets导入文本输入
从bokeh.doc导入curdoc
source=ColumnDataSource(dict(日期=[date(2014,3,i+1)表示范围内的i(20)],下载=[randint(01100)表示范围内的i(20)])
columns=[TableColumn(field=“dates”,title=“Date”,formatter=DateFormatter()),TableColumn(field=“downloads”,title=“downloads”)]
数据表=数据表(源=源,列=列,宽度=400,高度=280,可编辑=真,可重排序=假)
text_row=TextInput(value=None,title=“row index:”,width=420)
text\u column=TextInput(值=None,title=“列索引:”,宽度=420)
text\u date=TextInput(值=None,title=“date:,宽度=420)
text_downloads=TextInput(value=None,title=“downloads:”,width=420)
测试单元=TextInput(值=None,title=“单元内容:”,宽度=420)
源代码=“”“
var grid=document.getElementsByClassName('grid-canvas')[0]。子项;
变量行,列=“”;
对于(变量i=0,max=grid.length;i
我附上了运行代码时出错的图片。正如您所能看到的,我点击了第16行,显示的是第10行索引。

或者,我的其他代码(引用了我已经从本地工作服务器上的数据创建的许多不同的数据帧等):

将熊猫作为pd导入
pd.options.mode.chained_赋值=无
将日期时间导入为dt
输入数学
随机输入
作为pd进口熊猫
进口itertools
进口泡菜
从bokeh.layouts导入布局
从集合导入订单
从bokeh.models导入ColumnDataSource、Column、TableColumn、DateFormatter、DataTable、CustomJS、DataRange1d
从bokeh.plotting导入图,curdoc
source=ColumnDataSource(dict(products=dfNew['products'],prices=dfNew['Current prices']))
columns=[TableColumn(field=“products”,title=“products”),TableColumn(field=“prices”,title=“当前价格”)]
数据表=数据表(源=源,列=列,宽度=400,高度=350,可编辑=真,可重排序=假)
位置\源=列数据源(dict(行=[],列=[]))
prodPx=OrderedDict()
pVal=0
对于产品中的i:
key=str(i)
prodPx[key]=[(dfNew[‘当前价格’)[pVal]]
pVal+=1
noProd=OrderedDict()
kVal=0
对于产品中的i:
key=str(kVal)
noProd[key]=[i]
kVal+=1
prodpx_source=列数据源(prodpx)
noprod_source=ColumnDataSource(noprod)
#初始图表
x=新的日期
y=df[产品[0]]
sourceChart=ColumnDataSource(数据=dict(x=x,y=y))
图表=图形(标题=ccy+“图表”,x轴类型=日期时间,绘图宽度=1200,绘图高度=500)
图表。线条('x','y',源=源图表,线条宽度=3,线条α=0.6)
#回调
源代码=“”“
var grid=document.getElementsByClassName('grid-canvas')[0]。子项;
变量行,列=“”;
对于(变量i=0,max=grid.length;i
我的回调代码不适用于具有滚动条的表。从那时起,我更新了它,使其更加健壮(但它只适用于文档中的第一个表小部件)

从bokeh.io导入显示
从bokeh.layouts导入widgetbox
从bokeh.models导入ColumnDataSource,CustomJS
从…起
import pandas as pd
pd.options.mode.chained_assignment = None
import datetime as dt
import math
import random
import pandas as pd
import itertools
import pickle
from bokeh.layouts import layout
from collections import OrderedDict
from bokeh.models import ColumnDataSource, Column, TableColumn, DateFormatter, DataTable, CustomJS, DataRange1d
from bokeh.plotting import figure, curdoc

source = ColumnDataSource(dict(products=dfNew['Products'], prices=dfNew['Current Prices']))
columns = [TableColumn(field="products", title="Products"), TableColumn(field="prices", title="Current Prices")]
data_table = DataTable(source=source, columns=columns, width=400, height=350, editable=True, reorderable=False)
location_source = ColumnDataSource(dict(row=[], column=[]))

prodPx = OrderedDict()
pVal = 0
for i in products:
    key = str(i)
    prodPx[key] = [(dfNew['Current Prices'])[pVal]]
    pVal += 1

noProd = OrderedDict()
kVal = 0
for i in products:
    key = str(kVal)
    noProd[key] = [i]
    kVal += 1

prodpx_source = ColumnDataSource(prodPx)
noprod_source = ColumnDataSource(noProd)


#initial chart
x = new_dates
y = df[products[0]]
sourceChart = ColumnDataSource(data=dict(x=x, y=y))

chart = figure(title=ccy + ' Charting', x_axis_type='datetime', plot_width = 1200, plot_height=500)
chart.line('x', 'y', source=sourceChart, line_width=3, line_alpha=0.6)

#callbacks
source_code = """
var grid = document.getElementsByClassName('grid-canvas')[0].children;
var row, column = '';

for (var i = 0,max = grid.length; i < max; i++){
    if (grid[i].outerHTML.includes('active')){
        row = i;
        for (var j = 0, jmax = grid[i].children.length; j < jmax; j++)
            if(grid[i].children[j].outerHTML.includes('active')) {
                column = j; 
                source2.data = {row: [row], column: [column]};
            }
    }
}
source.change.emit();
source2.change.emit();
source3.change.emit();
source4.change.emit();
"""

#js callback
callback = CustomJS(args=dict(source=source, source2=location_source, source3=prodpx_source,
                              source4=noprod_source), code=source_code)

source.selected.js_on_change('indices', callback)

#python callback
def py_callback(attr, old, new):
    row = str((location_source.data['row'][0]))
    chartVals = (noprod_source.data[row][0])
    try:
        yVar = df[chartVals]
    except:
        yVar = df[totalProducts[0]]
    sourceChart.data = dict(x=x, y=yVar)
    source.selected.update(indices=[])
    print(location_source.data)

source.selected.on_change('indices', py_callback)
layout = layout([data_table], [chart])
curdoc().add_root(layout)


from bokeh.io import show
from bokeh.layouts import widgetbox
from bokeh.models import ColumnDataSource, CustomJS
from bokeh.models.widgets import DataTable,TableColumn

column_list = ['col1','col2','col3']

source = ColumnDataSource(data = {key:range(20) for key in column_list})

columns = [TableColumn(field=col, title=col) for col in column_list]

data_table = DataTable(source=source, columns=columns, width=400, height=280,selectable=True)

source_code = """
var grid = document.getElementsByClassName('grid-canvas')[0];

var active_row = grid.querySelectorAll('.active')[0];

if (active_row!=undefined){

    var active_row_ID = Number(active_row.children[0].innerText);

    for (var i=1, imax=active_row.children.length; i<imax; i++){
        if (active_row.children[i].className.includes('active')){
            var active_col_ID = i-1;
        }
    }

    console.log('row',active_row_ID);
    console.log('col',active_col_ID);

    var active_cells = grid.querySelectorAll('.active');
    for (i=0, imax=active_cells.length;i<imax;i++){
        active_cells[i].classList.remove('active');
    }

    cb_obj.indices = [];
}
"""

source.selected.js_on_change('indices', CustomJS(args={'source':source},code= source_code) )

show(widgetbox(data_table))