Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Responsive div widget Bokeh

Tags:

css

widget

bokeh

I'm trying to get a responsive div widget using Bokeh server in directory format and standard template.

I have made a template using bootstrap, with 3 areas :

  • top-left div widget to dynamically add text (log events, scrollable in case of overflow, goal: occupy full available space)
  • bottom-left controls (button widgets)
  • and full height right a bokeh plot.

Controls and plot are working as expected, observed behavior of //green div widget// :

  • vertically : initially of the good size, but is resized when adding text and expand below the controls (no scroll)
  • horizontally : initial width is fixed, but does not occupied full available width. When overflow, good behavior (scroll enable)

I tried without success different css tricks with the style parameter of div widget (width:100%, w-100 ..), using different sizing_mode. I'm out of ideas, any suggestions ?

Directory structure:

myapp
|
+---main.py
+---templates
    +---index.html

main.py :

from bokeh.plotting import curdoc, figure
from bokeh.models import ColumnDataSource
from bokeh.models.widgets import Button, Div
from bokeh.layouts import row

source = ColumnDataSource(dict(xs=[0, 1, 2, 3], ys=[0, 1, 4, 9]))

graph = figure(title="Graphique", name="graph", sizing_mode="stretch_both")
graph.line(x="xs", y="ys", source=source)

logDiv = Div(text="log",
             css_classes=["h-100"],
             style={"overflow": "scroll", "background-color": "green", 'width': '100%', "height": "100%"},
             name="log")

def add_text():
    logDiv.text = "Hohoho" + "<BR>" + logDiv.text
def add_long_text():
    logDiv.text = "HohohoHohohoHohohoHohohoHohohoHohohoHohohoHohohoHohohoHohohoHohohoHohohoHohohoHohohoHohoho" + "<BR>" + logDiv.text

add_text_btn = Button(label="add text")
add_long_text_btn = Button(label="add long text")
add_text_btn.on_click(add_text)
add_long_text_btn.on_click(add_long_text)

controls = row(add_text_btn, add_long_text_btn, name="controls", sizing_mode="stretch_both")

curdoc().add_root(logDiv)
curdoc().add_root(controls)
curdoc().add_root(graph)

index.html :

    {% extends base %}

{% block preamble %}
<!-- Bootstrap -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">

<!-- full page height -->
<style>
    body, html  {height: 100%;}
</style>
{% endblock %}

<!-- goes in body -->
{% block contents %}
<div class="container-fluid h-100">
    <div class="row h-100">

        <div class="col-3">
            <div class="row h-50">
                {{ embed(roots.log) }}
            </div>
            <div class="row h-50">
                {{ embed(roots.controls) }}
            </div>
        </div>


        <div class="col-9">
            {{ embed(roots.graph) }}
        </div>

    </div>
</div>

<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>

{% endblock %}
like image 707
Louc Avatar asked Apr 19 '26 08:04

Louc


1 Answers

I've followed a friend advice (encapsulation) and found an elegant solution : the div widget need to be encapsulated using a layout like row() or column() before being attached to document root.

Below is the solution, main addition is log = row(logDiv, name="log", sizing_mode="stretch_both")

Directory structure :

myapp
|
+---main.py
+---templates
    +---index.html

main.py :

from bokeh.plotting import curdoc, figure
from bokeh.models import ColumnDataSource
from bokeh.models.widgets import Button, Div
from bokeh.layouts import row

source = ColumnDataSource(dict(xs=[0, 1, 2, 3], ys=[0, 1, 4, 9]))

graph = figure(title="Graphique", name="graph", sizing_mode="stretch_both")
graph.line(x="xs", y="ys", source=source)

logDiv = Div(text="log",
             style={"overflow": "scroll", "background-color": "green", 'width': '100%', "height": "100%"},
             name="logDiv")
log = row(logDiv, name="log", sizing_mode="stretch_both")

def add_text():
    logDiv.text = "Hohoho" + "<BR>" + logDiv.text
def add_long_text():
    logDiv.text = "HohohoHohohoHohohoHohohoHohohoHohohoHohohoHohohoHohohoHohohoHohohoHohohoHohohoHohohoHohoho" + "<BR>" + logDiv.text

add_text_btn = Button(label="add text")
add_long_text_btn = Button(label="add long text")
add_text_btn.on_click(add_text)
add_long_text_btn.on_click(add_long_text)

controls = row(add_text_btn, add_long_text_btn, name="controls", sizing_mode="stretch_both")

curdoc().add_root(log)
curdoc().add_root(controls)
curdoc().add_root(graph)

index.html

{% extends base %}

{% block preamble %}
<!-- Bootstrap -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">

<!-- full page height -->
<style>
    body, html  {height: 100%;}
</style>
{% endblock %}

<!-- goes in body -->
{% block contents %}
<div class="container-fluid h-100">
    <div class="row h-100">

        <div class="col-3">
            <div class="row h-50">
                {{ embed(roots.log) }}
            </div>
            <div class="row h-50">
                {{ embed(roots.controls) }}
            </div>
        </div>


        <div class="col-9">
            {{ embed(roots.graph) }}
        </div>

    </div>
</div>

<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>

{% endblock %}
like image 79
Louc Avatar answered Apr 21 '26 22:04

Louc



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!