Search code examples
javascriptplotresponsivebokehjquery-ui-resizable

How to trigger BokehJS plot resize upon jquery-ui resize event?


I am trying to use BokehJS in a simple html page containing a div id="myMenu" that is made resizable using jquery-ui. I would like that the div id="myPlot" containing a BokehJS plot is dynamically resized to fill the rest of the window.

In the following example (which is the best I could get so far), despite using sizing_mode:'stretch_both' the only way I can trigger BokehJS plot resize is by manually resizing the web browser window.

Is it possible to trigger a BokehJS plot resize using javascript? What would be the function to be used? The plan would then be to use that function in a custom jquery-ui resize event handler.

EDIT: Example updated using solution provided on Github. Thanks!

<html>
<head>
    <link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.min.css" type="text/css" />
    <script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>

    <link rel="stylesheet" href="https://cdn.bokeh.org/bokeh/release/bokeh-1.1.0.min.css" type="text/css" />
    <link rel="stylesheet" href="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-1.1.0.min.css" type="text/css" />
    <link rel="stylesheet" href="https://cdn.bokeh.org/bokeh/release/bokeh-tables-1.1.0.min.css" type="text/css" />

    <script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-1.1.0.min.js"></script>
    <script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-1.1.0.min.js"></script>
    <script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-1.1.0.min.js"></script>
    <script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-gl-1.1.0.min.js"></script>
    <script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-api-1.1.0.min.js"></script>

    <!-- The order of CSS and JS imports above is important. -->
</head>
<body>
    <div style="display:table; width:100%; height:100%; margin:0px; border:0px; padding:0px;">
        <div style="display:table-row; width:100%; height:100%; margin:0px; border:0px; padding:0px;">
            <div id="myMenu" style="display:table-cell; width:25%; vertical-align:top; height:100%; margin:0px; border:0px; border-right:1px solid grey; padding:0px;">
                menu
            </div>
            <div id="myPlot" style="display:table-cell; height:100%; margin:0px; border:0px; padding:0px;"></div>
        </div>
    </div>
    <script type="text/javascript">
        // data to plot
        var source = new Bokeh.ColumnDataSource({
            data: { x: [0,1,2,3,4,5,6,7,8,9], y: [0,1,4,-2,2,5,0,2,1,1] }
        });

        // make the figure and add some tools
        var tools = "pan,crosshair,wheel_zoom,box_zoom,reset,save";

        var figure = new Bokeh.Plotting.figure({
            title:"demo plot",
            tools: tools,
            toolbar_location:"above",
            sizing_mode:"stretch_both"
        });

        var scatterData = figure.line({ field: "x" }, { field: "y" }, {
            source: source,
            line_width: 2
        });

        async function show(){

            //Show Bokeh figure
            var figure_view = await Bokeh.Plotting.show(figure,document.getElementById("myPlot"));

            //Make left menu container resizable
            ($('#myMenu').resizable({
                handles:'e',
                resize:function(event,ui){
                    figure_view.resize_layout();
                }
            }));
        }
        show();

    </script>
</body>
</html>

Solution

  • Working solution for Bokeh 1.1.0 as per github.com/bokeh/bokeh/issues/7132

    <html>
    <head>
        <link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.min.css" type="text/css" />
        <script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
        <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
    
        <link rel="stylesheet" href="https://cdn.bokeh.org/bokeh/release/bokeh-1.1.0.min.css" type="text/css" />
        <link rel="stylesheet" href="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-1.1.0.min.css" type="text/css" />
        <link rel="stylesheet" href="https://cdn.bokeh.org/bokeh/release/bokeh-tables-1.1.0.min.css" type="text/css" />
    
        <script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-1.1.0.min.js"></script>
        <script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-1.1.0.min.js"></script>
        <script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-1.1.0.min.js"></script>
        <script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-gl-1.1.0.min.js"></script>
        <script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-api-1.1.0.min.js"></script>
    
        <!-- The order of CSS and JS imports above is important. -->
    </head>
    <body>
        <div style="display:table; width:100%; height:100%; margin:0px; border:0px; padding:0px;">
            <div style="display:table-row; width:100%; height:100%; margin:0px; border:0px; padding:0px;">
                <div id="myMenu" style="display:table-cell; width:25%; vertical-align:top; height:100%; margin:0px; border:0px; border-right:1px solid grey; padding:0px;">
                    menu
                </div>
                <div id="myPlot" style="display:table-cell; height:100%; margin:0px; border:0px; padding:0px;"></div>
            </div>
        </div>
        <script type="text/javascript">
            // data to plot
            var source = new Bokeh.ColumnDataSource({
                data: { x: [0,1,2,3,4,5,6,7,8,9], y: [0,1,4,-2,2,5,0,2,1,1] }
            });
    
            // make the figure and add some tools
            var tools = "pan,crosshair,wheel_zoom,box_zoom,reset,save";
    
            var figure = new Bokeh.Plotting.figure({
                title:"demo plot",
                tools: tools,
                toolbar_location:"above",
                sizing_mode:"stretch_both"
            });
    
            var scatterData = figure.line({ field: "x" }, { field: "y" }, {
                source: source,
                line_width: 2
            });
    
            async function show(){
    
                //Show Bokeh figure
                var figure_view = await Bokeh.Plotting.show(figure,document.getElementById("myPlot"));
    
                //Make left menu container resizable
                ($('#myMenu').resizable({
                    handles:'e',
                    resize:function(event,ui){
                        figure_view.resize_layout();
                    }
                }));
            }
            show();
    
        </script>
    </body>
    </html>