Provide Jinja2 templates used by Bokeh to embed Bokeh documents and models in various ways.
AUTOLOAD_JS
Renders JavaScript code for “autoloading”.
The code automatically and asynchronously loads BokehJS (if necessary) and then replaces the AUTOLOAD_TAG <script> tag that calls it with the rendered model.
<script>
elementid (str) – the unique id for the script tag
js_urls (list) – URLs of JS files making up Bokeh library
css_urls (list) – CSS urls to inject
(function(root) { function now() { return new Date(); } var force = {{ force|default(False)|json }}; if (typeof root._bokeh_onload_callbacks === "undefined" || force === true) { root._bokeh_onload_callbacks = []; root._bokeh_is_loading = undefined; } {% block register_mimetype %} {% endblock %} {% block autoload_init %} {%- if elementid -%} var element = document.getElementById({{ elementid|json }}); if (element == null) { console.warn("Bokeh: autoload.js configured with elementid '{{ elementid }}' but no matching script tag was found.") } {%- endif %} {% endblock %} function run_callbacks() { try { root._bokeh_onload_callbacks.forEach(function(callback) { if (callback != null) callback(); }); } finally { delete root._bokeh_onload_callbacks } console.debug("Bokeh: all callbacks have finished"); } function load_libs(css_urls, js_urls, callback) { if (css_urls == null) css_urls = []; if (js_urls == null) js_urls = []; root._bokeh_onload_callbacks.push(callback); if (root._bokeh_is_loading > 0) { console.debug("Bokeh: BokehJS is being loaded, scheduling callback at", now()); return null; } if (js_urls == null || js_urls.length === 0) { run_callbacks(); return null; } console.debug("Bokeh: BokehJS not loaded, scheduling load and callback at", now()); root._bokeh_is_loading = css_urls.length + js_urls.length; function on_load() { root._bokeh_is_loading--; if (root._bokeh_is_loading === 0) { console.debug("Bokeh: all BokehJS libraries/stylesheets loaded"); run_callbacks() } } function on_error(url) { console.error("failed to load " + url); } for (let i = 0; i < css_urls.length; i++) { const url = css_urls[i]; const element = document.createElement("link"); element.onload = on_load; element.onerror = on_error.bind(null, url); element.rel = "stylesheet"; element.type = "text/css"; element.href = url; console.debug("Bokeh: injecting link tag for BokehJS stylesheet: ", url); document.body.appendChild(element); } const hashes = {{ bundle.hashes|json }}; for (let i = 0; i < js_urls.length; i++) { const url = js_urls[i]; const element = document.createElement('script'); element.onload = on_load; element.onerror = on_error.bind(null, url); element.async = false; element.src = url; if (url in hashes) { element.crossOrigin = "anonymous"; element.integrity = "sha384-" + hashes[url]; } console.debug("Bokeh: injecting script tag for BokehJS library: ", url); document.head.appendChild(element); } }; function inject_raw_css(css) { const element = document.createElement("style"); element.appendChild(document.createTextNode(css)); document.body.appendChild(element); } {% if bundle %} var js_urls = {{ bundle.js_urls|json }}; var css_urls = {{ bundle.css_urls|json }}; {% else %} var js_urls = {{ js_urls|json }}; var css_urls = {{ css_urls|json }}; {% endif %} var inline_js = [ {%- for css in (bundle.css_raw if bundle else css_raw) %} function(Bokeh) { inject_raw_css({{ css|json }}); }, {%- endfor %} {%- for js in (bundle.js_raw if bundle else js_raw) %} function(Bokeh) { {{ js|indent(6) }} }, {% endfor -%} function(Bokeh) { {% block inline_js %} {% endblock %} } ]; function run_inline_js() { {% block run_inline_js %} for (var i = 0; i < inline_js.length; i++) { inline_js[i].call(root, root.Bokeh); } {% endblock %} } if (root._bokeh_is_loading === 0) { console.debug("Bokeh: BokehJS loaded, going straight to plotting"); run_inline_js(); } else { load_libs(css_urls, js_urls, function() { console.debug("Bokeh: BokehJS plotting callback run at", now()); run_inline_js(); }); } }(window));
AUTOLOAD_NB_JS
{% extends "autoload_js.js" %} {% block register_mimetype %} {%- if register_mime -%} var JS_MIME_TYPE = 'application/javascript'; var HTML_MIME_TYPE = 'text/html'; var EXEC_MIME_TYPE = 'application/vnd.bokehjs_exec.v0+json'; var CLASS_NAME = 'output_bokeh rendered_html'; /** * Render data to the DOM node */ function render(props, node) { var script = document.createElement("script"); node.appendChild(script); } /** * Handle when an output is cleared or removed */ function handleClearOutput(event, handle) { var cell = handle.cell; var id = cell.output_area._bokeh_element_id; var server_id = cell.output_area._bokeh_server_id; // Clean up Bokeh references if (id != null && id in Bokeh.index) { Bokeh.index[id].model.document.clear(); delete Bokeh.index[id]; } if (server_id !== undefined) { // Clean up Bokeh references var cmd = "from bokeh.io.state import curstate; print(curstate().uuid_to_server['" + server_id + "'].get_sessions()[0].document.roots[0]._id)"; cell.notebook.kernel.execute(cmd, { iopub: { output: function(msg) { var id = msg.content.text.trim(); if (id in Bokeh.index) { Bokeh.index[id].model.document.clear(); delete Bokeh.index[id]; } } } }); // Destroy server and session var cmd = "import bokeh.io.notebook as ion; ion.destroy_server('" + server_id + "')"; cell.notebook.kernel.execute(cmd); } } /** * Handle when a new output is added */ function handleAddOutput(event, handle) { var output_area = handle.output_area; var output = handle.output; // limit handleAddOutput to display_data with EXEC_MIME_TYPE content only if ((output.output_type != "display_data") || (!Object.prototype.hasOwnProperty.call(output.data, EXEC_MIME_TYPE))) { return } var toinsert = output_area.element.find("." + CLASS_NAME.split(' ')[0]); if (output.metadata[EXEC_MIME_TYPE]["id"] !== undefined) { toinsert[toinsert.length - 1].firstChild.textContent = output.data[JS_MIME_TYPE]; // store reference to embed id on output_area output_area._bokeh_element_id = output.metadata[EXEC_MIME_TYPE]["id"]; } if (output.metadata[EXEC_MIME_TYPE]["server_id"] !== undefined) { var bk_div = document.createElement("div"); bk_div.innerHTML = output.data[HTML_MIME_TYPE]; var script_attrs = bk_div.children[0].attributes; for (var i = 0; i < script_attrs.length; i++) { toinsert[toinsert.length - 1].firstChild.setAttribute(script_attrs[i].name, script_attrs[i].value); toinsert[toinsert.length - 1].firstChild.textContent = bk_div.children[0].textContent } // store reference to server id on output_area output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE]["server_id"]; } } function register_renderer(events, OutputArea) { function append_mime(data, metadata, element) { // create a DOM node to render to var toinsert = this.create_output_subarea( metadata, CLASS_NAME, EXEC_MIME_TYPE ); this.keyboard_manager.register_events(toinsert); // Render to node var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]}; render(props, toinsert[toinsert.length - 1]); element.append(toinsert); return toinsert } /* Handle when an output is cleared or removed */ events.on('clear_output.CodeCell', handleClearOutput); events.on('delete.Cell', handleClearOutput); /* Handle when a new output is added */ events.on('output_added.OutputArea', handleAddOutput); /** * Register the mime type and append_mime function with output_area */ OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, { /* Is output safe? */ safe: true, /* Index of renderer in `output_area.display_order` */ index: 0 }); } // register the mime type if in Jupyter Notebook environment and previously unregistered if (root.Jupyter !== undefined) { var events = require('base/js/events'); var OutputArea = require('notebook/js/outputarea').OutputArea; if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) { register_renderer(events, OutputArea); } } {%- endif -%} {% endblock %} {% block autoload_init %} if (typeof (root._bokeh_timeout) === "undefined" || force === true) { root._bokeh_timeout = Date.now() + {{ timeout|default(0)|json }}; root._bokeh_failed_load = false; } var NB_LOAD_WARNING = {'data': {'text/html': "<div style='background-color: #fdd'>\n"+ "<p>\n"+ "BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \n"+ "may be due to a slow or bad network connection. Possible fixes:\n"+ "</p>\n"+ "<ul>\n"+ "<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\n"+ "<li>use INLINE resources instead, as so:</li>\n"+ "</ul>\n"+ "<code>\n"+ "from bokeh.resources import INLINE\n"+ "output_notebook(resources=INLINE)\n"+ "</code>\n"+ "</div>"}}; function display_loaded() { var el = document.getElementById({{ elementid|json }}); if (el != null) { el.textContent = "BokehJS is loading..."; } if (root.Bokeh !== undefined) { if (el != null) { el.textContent = "BokehJS " + root.Bokeh.version + " successfully loaded."; } } else if (Date.now() < root._bokeh_timeout) { setTimeout(display_loaded, 100) } } {% endblock %} {% block run_inline_js %} if (root.Bokeh !== undefined || force === true) { {{ super() }} {%- if elementid -%} if (force === true) { display_loaded(); } {%- endif -%} } else if (Date.now() < root._bokeh_timeout) { setTimeout(run_inline_js, 100); } else if (!root._bokeh_failed_load) { console.log("Bokeh: BokehJS failed to load within specified timeout."); root._bokeh_failed_load = true; } else if (force !== true) { var cell = $(document.getElementById({{ elementid|json }})).parents('.cell').data().cell; cell.output_area.append_execute_result(NB_LOAD_WARNING) } {% endblock %}
AUTOLOAD_REQUEST_TAG
Renders <script> tags that automatically load BokehJS (if necessary) and then renders a Bokeh model or document. The document may be specified as either an embedded doc ID or a server session ID. If a specific model ID is not specified, the entire document will be rendered.
src_path (str) – path to AUTOLOAD script
elementid (str) – the a unique id for the script tag
modelid (str) – The Bokeh model id for the object to render (if missing, render the whole doc; if present, only render the one model)
docid (str) – The id of the embedded Bokeh document to render
headers (dict) – A dictionary of HTTP request headers to include in the request
Note
This script injects a <div> in place, so must be placed under <body>.
<div>
<body>
<script id="{{ elementid }}"> var xhr = new XMLHttpRequest() xhr.responseType = 'blob'; xhr.open('GET', "{{ src_path }}", true); {% for header, value in headers.items() %} xhr.setRequestHeader("{{ header }}", "{{ value }}") {% endfor %} xhr.onload = function (event) { var script = document.createElement('script'), src = URL.createObjectURL(event.target.response); script.src = src; document.body.appendChild(script); }; xhr.send(); </script>
AUTOLOAD_TAG
<script src="{{ src_path }}" id="{{ elementid }}"></script>
CSS_RESOURCES
Renders HTML that loads Bokeh CSS according to the configuration in a Resources object.
css_files (list[str]) – a list of URIs for CSS files to include
css_raw (list[str]) – a list of raw CSS snippets to put between <style> tags
<style>
{%- for file in css_files %} <link rel="stylesheet" href="{{ file }}" type="text/css" /> {%- endfor %} {%- for css in css_raw %} <style> {{ css|indent(8) }} </style> {%- endfor %}
DOC_JS
{% extends "try_run.js" %} {% block code_to_run %} var docs_json = {{ docs_json }}; var render_items = {{ render_items }}; root.Bokeh.embed.embed_items(docs_json, render_items{%- if app_path -%}, "{{ app_path }}" {%- endif -%}{%- if absolute_url -%}, "{{ absolute_url }}" {%- endif -%}); {% endblock %}
DOC_NB_JS
{% extends "try_run.js" %} {% block code_to_run %} var docs_json = {{ docs_json }}; var render_items = {{ render_items }}; root.Bokeh.embed.embed_items_notebook(docs_json, render_items); {% endblock %}
FILE
Renders Bokeh models into a basic .html file.
title (str) – value for <title> tags
<title>
plot_resources (str) – typically the output of RESOURCES
plot_script (str) – typically the output of PLOT_SCRIPT
Users can customize the file output by providing their own Jinja2 template that accepts these same parameters.
{% from macros import embed %} <!DOCTYPE html> <html lang="en"> {% block head %} <head> {% block inner_head %} <meta charset="utf-8"> <title>{% block title %}{{ title | e if title else "Bokeh Plot" }}{% endblock %}</title> {% block preamble %}{% endblock %} {% block resources %} {% block css_resources %} {{ bokeh_css | indent(8) if bokeh_css }} {% endblock %} {% block js_resources %} {{ bokeh_js | indent(8) if bokeh_js }} {% endblock %} {% endblock %} {% block postamble %}{% endblock %} {% endblock %} </head> {% endblock %} {% block body %} <body> {% block inner_body %} {% block contents %} {% for doc in docs %} {{ embed(doc) if doc.elementid }} {% for root in doc.roots %} {% block root scoped %} {{ embed(root) | indent(10) }} {% endblock %} {% endfor %} {% endfor %} {% endblock %} {{ plot_script | indent(8) }} {% endblock %} </body> {% endblock %} </html>
JS_RESOURCES
Renders HTML that loads BokehJS JavaScript code and CSS according to the configuration in a Resources object.
hashes (dict[str, str]) – a map of filenames for to SRI hashes
js_files (list[str]) – a list of URIs for JS files to include
js_raw (list[str]) – a list of raw JS snippets to put between <style> tags
{%- for file in js_files %} <script type="text/javascript" src="{{ file }}" {%- if hashes and file in hashes %} integrity="sha384-{{ hashes[file] }}" crossorigin="anonymous"{%- endif -%} ></script> {%- endfor %} {%- for js in js_raw %} <script type="text/javascript"> {{ js|indent(8) }} </script> {%- endfor %}
NOTEBOOK_LOAD
Renders HTML for loading BokehJS JavaScript code and CSS into a Jupyter Notebook according to a Resources object.
verbose (bool) – whether to display verbose info about BokehJS configuration, etc
bokeh_version (str) – the current version of Bokeh
js_info (str) – information about the location, version, etc. of BokehJS code
css_info (str) – information about the location, version, etc. of BokehJS css
warnings (list[str]) – a list of warnings to display to user
<div class="bk-root"> <a href="https://bokeh.org" target="_blank" class="bk-logo bk-logo-small bk-logo-notebook"></a> <span id="{{ element_id }}">Loading BokehJS ...</span> </div> {%- if verbose %} <style> p.bokeh_notebook { margin-left: 24px; } table.bokeh_notebook { border: 1px solid #e7e7e7; margin: 5px; margin-left: 24px; width: 80%; } tr.bokeh_notebook { border: 1px solid #e7e7e7; background-color: #FFF; } th.bokeh_notebook { border: 1px solid #e7e7e7; background-color: #f8f8f8; text-align: center; } td.bokeh_notebook { border: 1px solid #e7e7e7; background-color: #d2d7ec; text-align: left; } </style> <p class="bokeh_notebook">Using Settings:</p> <table class="bokeh_notebook"> <tr class="bokeh_notebook"> <th class="bokeh_notebook">Bokeh</th> <th class="bokeh_notebook">version</th> <td class="bokeh_notebook">{{ bokeh_version }}</td> </tr> <tr class="bokeh_notebook"> <th class="bokeh_notebook" rowspan="2">BokehJS</th> <th class="bokeh_notebook">js</th> <td class="bokeh_notebook">{{ js_info }}</td> </tr> <tr class="bokeh_notebook"> <th class="bokeh_notebook">css</th> <td class="bokeh_notebook">{{ css_info }}</td> </tr> </table> {%- endif %} {%- for warning in warnings %} <p style="background-color: #f2d7dc;">{{ warning }}</p> {%- endfor %}
PLOT_DIV
Renders a basic plot div, that can be used in conjunction with PLOT_JS.
elementid (str) – a unique identifier for the <div> a PLOT_JS template should be configured with the same elementid
elementid
{% from macros import embed %} {{ embed(doc) if doc.elementid }} {% for root in doc.roots %} {{ embed(root) }} {% endfor %}
ROOT_DIV
{% from macros import embed %} {{ embed(root) }}
SCRIPT_TAG
Renders a <script> tag for raw JavaScript code.
js_code (str) – raw JavaScript code to put in the tag.
<script type="{{ type }}"{%if id %} id="{{ id }}"{% endif %}> {{ js_code }} </script>