bokeh.core.templates#
提供 Bokeh 用于以各种方式嵌入 Bokeh 文档和模型的 Jinja2 模板。
- AUTOLOAD_JS = <Template 'autoload_js.js'>#
模板:autoload_js.js
'use strict'; (function(root) { function now() { return new Date(); } const force = {{ force|default(False)|tojson }}; 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 -%} const element = document.getElementById({{ elementid|tojson }}); 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); } 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; 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 %} const js_urls = {{ bundle.js_urls|map(attribute="url")|list|tojson }}; const css_urls = {{ bundle.css_urls|map(attribute="url")|list|tojson }}; {% else %} const js_urls = {{ js_urls|tojson }}; const css_urls = {{ css_urls|tojson }}; {% endif %} const inline_js = [ {%- for css in (bundle.css_raw if bundle else css_raw) %} function(Bokeh) { inject_raw_css({{ css|tojson }}); }, {%- 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 (let 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 = <Template 'autoload_nb_js.js'>#
模板:autoload_nb_js.js
{% extends "autoload_js.js" %} {% block register_mimetype %} {%- if register_mime -%} const JS_MIME_TYPE = 'application/javascript'; const HTML_MIME_TYPE = 'text/html'; const EXEC_MIME_TYPE = 'application/vnd.bokehjs_exec.v0+json'; const CLASS_NAME = 'output_bokeh rendered_html'; /** * Render data to the DOM node */ function render(props, node) { const script = document.createElement("script"); node.appendChild(script); } /** * Handle when an output is cleared or removed */ function handleClearOutput(event, handle) { function drop(id) { const view = Bokeh.index.get_by_id(id) if (view != null) { view.model.document.clear() Bokeh.index.delete(view) } } const cell = handle.cell; const id = cell.output_area._bokeh_element_id; const server_id = cell.output_area._bokeh_server_id; // Clean up Bokeh references if (id != null) { drop(id) } if (server_id !== undefined) { // Clean up Bokeh references const cmd_clean = "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_clean, { iopub: { output: function(msg) { const id = msg.content.text.trim() drop(id) } } }); // Destroy server and session const cmd_destroy = "import bokeh.io.notebook as ion; ion.destroy_server('" + server_id + "')"; cell.notebook.kernel.execute(cmd_destroy); } } /** * Handle when a new output is added */ function handleAddOutput(event, handle) { const output_area = handle.output_area; const 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 } const 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) { const bk_div = document.createElement("div"); bk_div.innerHTML = output.data[HTML_MIME_TYPE]; const script_attrs = bk_div.children[0].attributes; for (let 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 const toinsert = this.create_output_subarea( metadata, CLASS_NAME, EXEC_MIME_TYPE ); this.keyboard_manager.register_events(toinsert); // Render to node const 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) { const events = require('base/js/events'); const 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)|tojson }}; root._bokeh_failed_load = false; } const 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(error = null) { const el = document.getElementById({{ elementid|tojson }}); if (el != null) { const html = (() => { if (typeof root.Bokeh === "undefined") { if (error == null) { return "BokehJS is loading ..."; } else { return "BokehJS failed to load."; } } else { const prefix = `BokehJS ${root.Bokeh.version}`; if (error == null) { return `${prefix} successfully loaded.`; } else { return `${prefix} <b>encountered errors</b> while loading and may not function as expected.`; } } })(); el.innerHTML = html; if (error != null) { const wrapper = document.createElement("div"); wrapper.style.overflow = "auto"; wrapper.style.height = "5em"; wrapper.style.resize = "vertical"; const content = document.createElement("div"); content.style.fontFamily = "monospace"; content.style.whiteSpace = "pre-wrap"; content.style.backgroundColor = "rgb(255, 221, 221)"; content.textContent = error.stack ?? error.toString(); wrapper.append(content); el.append(wrapper); } } else if (Date.now() < root._bokeh_timeout) { setTimeout(() => display_loaded(error), 100); } } {% endblock %} {% block run_inline_js %} if (root.Bokeh !== undefined || force === true) { try { {{ super() }} } catch (error) { {%- if elementid -%} display_loaded(error); {%- endif -%} throw error; } {%- 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) { const cell = $(document.getElementById({{ elementid|tojson }})).parents('.cell').data().cell; cell.output_area.append_execute_result(NB_LOAD_WARNING) } {% endblock %}
- AUTOLOAD_REQUEST_TAG = <Template 'autoload_request_tag.html'>#
渲染
<script>
标签,这些标签会自动加载 BokehJS(如果需要),然后渲染 Bokeh 模型或文档。文档可以指定为嵌入的文档 ID 或服务器会话 ID。如果没有指定特定的模型 ID,则会渲染整个文档。- 参数:
注意
此脚本在适当位置注入一个
<div>
,因此必须放在<body>
下。模板:autoload_request_tag.html
<script id="{{ elementid }}"> (function() { const xhr = new XMLHttpRequest() xhr.responseType = 'blob'; xhr.open('GET', "{{ src_path }}", true); {% for header, value in headers.items() %} xhr.setRequestHeader("{{ header }}", "{{ value }}") {% endfor %} xhr.withCredentials = {{ with_credentials | tojson }}; xhr.onload = function (event) { const script = document.createElement('script'); const src = URL.createObjectURL(event.target.response); script.src = src; document.body.appendChild(script); }; xhr.send(); })(); </script>
- AUTOLOAD_TAG = <Template 'autoload_tag.html'>#
渲染
<script>
标签,这些标签会自动加载 BokehJS(如果需要),然后渲染 Bokeh 模型或文档。文档可以指定为嵌入的文档 ID 或服务器会话 ID。如果没有指定特定的模型 ID,则会渲染整个文档。- 参数:
注意
此脚本在适当位置注入一个
<div>
,因此必须放在<body>
下。模板:autoload_tag.html
<script src="{{ src_path }}" id="{{ elementid }}"></script>
- CSS_RESOURCES = <Template 'css_resources.html'>#
渲染根据 Resources 对象中的配置加载 Bokeh CSS 的 HTML。
模板:css_resources.html
{% for file in css_files %} <link rel="stylesheet" href="{{ file }}" type="text/css" /> {% endfor %} {% for css in css_raw %} <style> {{ css }} </style> {% endfor %}
- DOC_JS = <Template 'doc_js.js'>#
模板:doc_js.js
{% extends "try_run.js" %} {% block code_to_run %} const docs_json = {{ docs_json }}; const 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 = <Template 'doc_nb_js.js'>#
模板:doc_nb_js.js
{% extends "try_run.js" %} {% block code_to_run %} const docs_json = {{ docs_json }}; const render_items = {{ render_items }}; void root.Bokeh.embed.embed_items_notebook(docs_json, render_items); {% endblock %}
- FILE = <Template 'file.html'>#
将 Bokeh 模型渲染到基本的 .html 文件中。
- 参数:
用户可以通过提供接受这些相同参数的自己的 Jinja2 模板来自定义文件输出。
模板:file.html
{% 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 %} <style> html, body { box-sizing: border-box; display: flow-root; height: 100%; margin: 0; padding: 0; } </style> {% block css_resources -%} {{- bokeh_css if bokeh_css }} {%- endblock css_resources %} {% block js_resources -%} {{ bokeh_js if bokeh_js }} {%- endblock js_resources %} {% endblock resources %} {% block postamble %}{% endblock %} {% endblock inner_head %} </head> {% endblock head%} {% 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) }} {% endblock %} {% endfor %} {% endfor %} {% endblock contents %} {{ plot_script | indent(4) }} {% endblock inner_body %} </body> {% endblock body%} </html>
- JS_RESOURCES = <Template 'js_resources.html'>#
根据 Resources 对象中的配置,渲染加载 BokehJS JavaScript 代码和 CSS 的 HTML。
- 参数:
模板:js_resources.html
{% for file in js_files %} <script type="text/javascript" src="{{ file }}"></script> {% endfor %} {% for js in js_raw %} <script type="text/javascript"> {{ js }} </script> {% endfor %}
- NOTEBOOK_LOAD = <Template 'notebook_load.html'>#
根据 Resources 对象,渲染将 BokehJS JavaScript 代码和 CSS 加载到 Jupyter Notebook 中的 HTML。
- 参数:
模板:notebook_load.html
<style> .bk-notebook-logo { display: block; width: 20px; height: 20px; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAAOkSURBVDiNjZRtaJVlGMd/1/08zzln5zjP1LWcU9N0NkN8m2CYjpgQYQXqSs0I84OLIC0hkEKoPtiH3gmKoiJDU7QpLgoLjLIQCpEsNJ1vqUOdO7ppbuec5+V+rj4ctwzd8IIbbi6u+8f1539dt3A78eXC7QizUF7gyV1fD1Yqg4JWz84yffhm0qkFqBogB9rM8tZdtwVsPUhWhGcFJngGeWrPzHm5oaMmkfEg1usvLFyc8jLRqDOMru7AyC8saQr7GG7f5fvDeH7Ej8CM66nIF+8yngt6HWaKh7k49Soy9nXurCi1o3qUbS3zWfrYeQDTB/Qj6kX6Ybhw4B+bOYoLKCC9H3Nu/leUTZ1JdRWkkn2ldcCamzrcf47KKXdAJllSlxAOkRgyHsGC/zRday5Qld9DyoM4/q/rUoy/CXh3jzOu3bHUVZeU+DEn8FInkPBFlu3+nW3Nw0mk6vCDiWg8CeJaxEwuHS3+z5RgY+YBR6V1Z1nxSOfoaPa4LASWxxdNp+VWTk7+4vzaou8v8PN+xo+KY2xsw6une2frhw05CTYOmQvsEhjhWjn0bmXPjpE1+kplmmkP3suftwTubK9Vq22qKmrBhpY4jvd5afdRA3wGjFAgcnTK2s4hY0/GPNIb0nErGMCRxWOOX64Z8RAC4oCXdklmEvcL8o0BfkNK4lUg9HTl+oPlQxdNo3Mg4Nv175e/1LDGzZen30MEjRUtmXSfiTVu1kK8W4txyV6BMKlbgk3lMwYCiusNy9fVfvvwMxv8Ynl6vxoByANLTWplvuj/nF9m2+PDtt1eiHPBr1oIfhCChQMBw6Aw0UulqTKZdfVvfG7VcfIqLG9bcldL/+pdWTLxLUy8Qq38heUIjh4XlzZxzQm19lLFlr8vdQ97rjZVOLf8nclzckbcD4wxXMidpX30sFd37Fv/GtwwhzhxGVAprjbg0gCAEeIgwCZyTV2Z1REEW8O4py0wsjeloKoMr6iCY6dP92H6Vw/oTyICIthibxjm/DfN9lVz8IqtqKYLUXfoKVMVQVVJOElGjrnnUt9T9wbgp8AyYKaGlqingHZU/uG2NTZSVqwHQTWkx9hxjkpWDaCg6Ckj5qebgBVbT3V3NNXMSiWSDdGV3hrtzla7J+duwPOToIg42ChPQOQjspnSlp1V+Gjdged7+8UN5CRAV7a5EdFNwCjEaBR27b3W890TE7g24NAP/mMDXRWrGoFPQI9ls/MWO2dWFAar/xcOIImbbpA3zgAAAABJRU5ErkJggg==); } </style> <div> <a href="https://bokeh.org.cn" target="_blank" class="bk-notebook-logo"></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 = <Template 'plot_div.html'>#
渲染一个基本的绘图 div,可与 PLOT_JS 结合使用。
- 参数:
elementid (str) –
<div>
的唯一标识符,PLOT_JS 模板应配置为具有相同的elementid
模板:plot_div.html
{% from macros import embed %} {{ embed(doc) if doc.elementid }} {% for root in doc.roots %} {{ embed(root) }} {% endfor %}
- ROOT_DIV = <Template 'root_div.html'>#
模板:root_div.html
{% from macros import embed %} {{ embed(root) }}