散景中的 OpenURL - 在同一选项卡中打开

OpenURL in bokeh - open in same tab

考虑下面来自 the Bokeh Docs 的示例,有没有一种方法可以调整 TapTool,这样当我点击一个圆圈时,我会转到同一选项卡上的 url 而不是打开一个新标签?文档字符串表明唯一的行为是打开一个新选项卡,但也许有一个 CustomJS 解决方法或其他一些 hack 来解决这个问题?

from bokeh.models import ColumnDataSource, OpenURL, TapTool
from bokeh.plotting import figure, output_file, show

output_file("openurl.html")

p = figure(plot_width=400, plot_height=400,
       tools="tap", title="Click the Dots")

source = ColumnDataSource(data=dict(
    x=[1, 2, 3, 4, 5],
    y=[2, 5, 8, 2, 7],
    color=["navy", "orange", "olive", "firebrick", "gold"]
    ))

p.circle('x', 'y', color='color', size=20, source=source)

url = "http://www.colors.commutercreative.com/@color/"
taptool = p.select(type=TapTool)
taptool.callback = OpenURL(url=url)

show(p)

我包装了一些 javascript 但没有成功(借用 this question 但有点不知道如何实现它)。这导致没有 link 打开:

callback = CustomJS(args=dict(source=source), code="""          
        url = data['url']
        window.open(url,"_self");
    """)    

taptool = p.select(type=TapTool)
taptool.callback = callback

我还尝试使用 OpenURL 的 tag 关键字将 link 视为 <a> 标记。这是一次盲目的尝试,因为我找不到任何关于如何正确使用这个 tag 术语的信息。这里没有运气。

url = "http://www.colors.commutercreative.com/@color/"
taptool = p.select(type=TapTool)
taptool.callback = OpenURL(url=url, tags=["_self"])

我知道 Bokeh 仍然很新,所以可能此功能尚不可用。我仍然认为,如果您足够了解 javascript(我显然不了解),就会有解决方法。

tags是一个尘封的特征,与此无关。它们只是允许您将一些任意信息附加到 Bokeh Model,如果您稍后查询对象图以查找特定模型,这会有所帮助。


从 Bokeh 0.12.3 开始,OpenURL 不支持这个,它只是调用 window.open:

https://github.com/bokeh/bokeh/blob/master/bokehjs/src/coffee/models/callbacks/open_url.coffee#L18

window.openname 参数添加新的 属性 仅需几行代码。我建议在 issue tracker 上打开一个功能请求问题。如果您有兴趣通过 PR 来实现此功能,我们总是很乐意帮助新贡献者入门。


这也可以通过 CustomJS 回调来完成。如果您只是想在单击圆圈时始终打开一个固定的 URL,则类似于

callback = CustomJS(args=dict(source=source), code="""          
    window.open("http://foo.com" ,"_self");
    """)    

如果您的数据源中有一列具有完整的 URL 并且您想根据所选索引选择一个,您需要做一些更像 OpenURL 回调的事情做:从数据源中获取选定的索引,然后使用选定的索引从数据源中的列中获取 URL, 然后 调用 window.open。这是一个完整的例子:

从bokeh.plotting导入图,output_file,显示 从 bokeh.models 导入 CustomJS、ColumnDataSource、TapTool

source = ColumnDataSource(data=dict(
    x = [1, 2],
    y = [3, 4],
    url = ["http://google.com", "http://bing.com"],
))

p = figure(tools="tap")
p.circle('x', 'y', size=15, source=source)

code = """
selection = require("core/util/selection")
indices = selection.get_indices(source)
for (i = 0; i < indices.length; i++) {
    ind = indices[i]
    url = source.data['url'][ind]
    window.open(url, "_self")
}
"""

taptool = p.select(type=TapTool)
taptool.callback = CustomJS(args=dict(source=source), code=code)

output_file("/tmp/foo.html")

show(p)