Is there a way to make a scrolling div textbox snap to the end and stay there when new text is added?
I’d like to have additional text come into the scrolling textbox and have it be displayed rather than forcing the user to use the scrollbar to scroll down. The point of the scrollbar is to keep useful output available for debugging.
But if the new text arrives at the bottom and is not visible by default, it forces the user to scroll down to see the most recent. Backwards is a little confusing. New text should enter at the bottom and be immediately visible.
An example with a scrollbar is from here. The following bokeh serve
example illustrates the issue.
Run with:
bokeh serve --show div_textbox_scrolling_alignment_snap.py
Filename div_textbox_scrolling_alignment_snap.py
:
from bokeh.layouts import column, layout, row
from bokeh.io import curdoc
from bokeh.models import Button
from bokeh.models.widgets import Div
from collections import deque
import subprocess
import sys
from queue import Queue
import random
import string
console_output_lines = 10
style_dict={'overflow-y':'scroll','height':'{0}px'.format(20*console_output_lines)}
web_console_div = Div(text='', width=800, height=20*console_output_lines, background='orange', style=style_dict)
def random_str(len=10):
return ''.join(random.sample( string.ascii_lowercase + string.ascii_uppercase + string.digits, len))
doc=curdoc() # make a copy so bokeh server and thread use same curdoc()
qProcLine=Queue()
msg_list = deque([])
def print_subproc_output():
global msg_list
msg_list.append( qProcLine.get() )
m=''
for msg in msg_list:
m += '{0}<br>'.format(msg)
web_console_div.text = m
# -----------------------------------------------------------------------------
cnt=0
def bt_add_lines_callback():
global cnt
for line in range(3):
cnt+=1
qProcLine.put( '[{0}] hello, random string of random length {1}'.format(cnt,random_str( int(random.uniform(10,40)) )) )
doc.add_next_tick_callback(print_subproc_output)
bt_add_lines = Button(label="Add 3 lines" , button_type="success", width=200)
bt_add_lines.on_click(bt_add_lines_callback)
# -----------------------------------------------------------------------------
def add_whitespace():
qProcLine.put( ' ' )
doc.add_next_tick_callback(print_subproc_output)
bt_space = Button(label="add whitespace" , button_type="success", width=50)
bt_space.on_click(add_whitespace)
## arrange all map views in a grid layout then add to the document
layout = layout([
[bt_add_lines,bt_space],
[web_console_div] ])#, sizing_mode='fixed') # "fixed", "stretch_both", "scale_width", "scale_height", "scale_both"
doc.add_root(layout)
Screenshot 1 illustrating the issue:
Screenshot 2 illusrating the question: