我找到了一个可以开始的解决方案。让我们从代码开始,接下来会有解释。
这是python代码:
import dash
import dash_html_components as html
import dash_core_components as dcc
app = dash.Dash(__name__)
box_style = dict(border='1px solid', margin='15px', padding='10px')
app.layout = html.Div(id='wrapper', children=[
html.P(id='selection-container', children='This text is selectable. Select here.', style=box_style),
html.P(id='other-container', children='Selecting this text will not work.', style=box_style),
dcc.Input(id='selection-target', value='', style=dict(display='none')),
html.Button(id='submit', children='Submit selection'),
html.P(id='callback-result', children=''),
])
@app.callback(
dash.dependencies.Output('callback-result', 'children'),
[dash.dependencies.Input('submit', 'n_clicks')],
[dash.dependencies.State('selection-target', 'value')],)
def update_output(n_clicks, value):
if value:
return html.Span(f'Selected string: "{value}"', style=dict(color='green'))
return html.Span('Nothing selected', style=dict(color='red'))
if __name__ == '__main__':
app.run_server(debug=True)
现在是一些 JavaScript。您需要将其放在名为“assets”的目录下的 JS 文件中(例如 assets/custom.js;解释为 here):
document.addEventListener('mouseup', () => {
var sel = window.getSelection();
var sel_str = sel.toString();
var target_value = '';
if (sel_str.length > 0) {
var pid = sel.focusNode.parentNode.id;
if (pid == 'selection-container') {
target_value = sel_str;
}
}
// Way to set value of React input
var input = document.getElementById('selection-target');
var nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value").set;
nativeInputValueSetter.call(input, target_value);
var ev2 = new Event('input', {bubbles: true});
input.dispatchEvent(ev2);
});
现在解释一下:代码创建了两个 HTML P 元素,一个是可选的,另一个不是。当在可选框中选择文本并单击按钮时,所选文本通过回调显示在第三个输出 P 中。这是通过使用所选文本更新隐藏文本输入的值来实现的(使用与 React 框架兼容的方法)。单击该按钮会触发一个回调,该回调将该值作为状态接收。隐藏的输入可以更改为任何其他类型的输入,我想文本区域也可以,但我还没有测试过。
有几点需要注意:JS 事件捕获有点古怪,而且远未完成。捕获文档的“mouse up”事件并不理想,您应该能够想到更好的方法。此外,如果您从不可选择的 P 开始选择并向后选择到可选择的 P,则该事件将被触发,因此您也需要注意这一点。
希望这会有所帮助。请用您最终选择的解决方案更新我们。