Adding a custom datepicker to bokeh standard text input - python

I'm trying to add a standard datepicker (like air datepicker) to a standard bokeh text input.
I added the JS references and I'm linking a class in the text input field like:
event = TextInput(title=u"Event Date", value=' ', css_classes=['datepicker-here'])
In theory, that should work, yet, it is not...
I also tried with other standard datepicker, to no success.
Here is another case: flatpicker.
A simple datepicker which works perfectly with this setup:
Create a simple text input:
event = TextInput(title=u"event", css_classes=['flatpkr'])
and put the required js code in the template.
flatpicker examples here (how it should work):
$("input[type='text']").flatpickr({
enableTime: true,
dateFormat: "F, d Y H:i"
});
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/flatpickr/4.2.3/flatpickr.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/flatpickr/4.2.3/themes/dark.css">
</head>
<body>
<div>
<input type="text" placeholder="Please select Date Time">
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/flatpickr/4.2.3/flatpickr.js"></script>
</body>
If this is set in a plain webpage, everything is working properly. In Bokeh it does not, although I set exactly the same code in the template
{% extends base %}
{% block postamble %}
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/flatpickr/4.2.3/flatpickr.css">
{% endblock %}
{% block contents %}
{{ super() }}
<!-- JS Scripts -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<!-- Flatpicker -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/flatpickr/4.2.3/flatpickr.js"></script>
<script type="text/javascript">
flatpickr("input[type='text']", {
"minDate": new Date().fp_incr(1)
});
</script>
{% endblock %}

The extra information confirms what I thought you intended, but is not actually enough to run and investigate. That said, contrary to your supposition "In theory, that should work", I would actually never expect this to work. And the reason is that declaring a Bokeh TextInput does mean "just dump a bare <input> in the DOM". Rather, there is an entire JS implementation and CSS that Bokeh provides to support its version of a text input widget. In general, I have zero confidence that it would ever "just work" to have two different JS libraries fighting to control the same DOM element in their own separate ways.
If you want to do this sort of thing (i.e. integrate outside widgets seamlessly with Bokeh), it's possible, but the usual mechanism is by Extending Bokeh. In particular see the example Adding a Custom Widget. A custom extension will have a Python object that represents it and that is automatically synchronized the same as any other Bokeh object.
Another (simpler) possibility: You could put HTML (including your plain <input>) in a Bokeh Div. Bokeh won't try to style or control any DOM elements added inside a Div. That might reasonably be expected to work (though I have not tried). A widget added this way will not have a Python counterpart that it is automatically synced with, but its not clear what your actual requirements are, so that might be fine.

Related

Is there a way to get a python value to an html <p>?

I'm making a somewhat simple python script + html site to get simple values from an Excel document.
I was able to use the "xlrd" library to get the exact cell which I needed and used a print statement to see if it worked.
Right now, I can't find a way to use that python value and get it inside a simple "h1 or p" in html.
Many people use "django" or "flask" to work with python and html, but I can't find the time to learn "django" or "flask", and need a quick solution (if it's even possible using vanilla python and html).
Here is the simple python code:
import xlrd
location = ("C:/Users/Usuario/Desktop/website-client/excels/FTHAgg.xlsx")
wb = xlrd.open_workbook(location)
sheet = wb.sheet_by_index(0)
# For row 0 and column 0
print(sheet.cell_value(4, 0))
And here is the html:
<html>
<head>
<link rel="stylesheet" href="rh.css">
<link href="https://fonts.googleapis.com/css?family=Noto+Sans+JP&display=swap" rel="stylesheet">
</head>
<body>
<nav>
<ul class="navbar">
<li><a class="active" href="rh.html">RH</a></li>
<li>GVT</li>
<li>FTH</li>
</ul>
</nav>
# here is where i'd like the paragraph containing the value go
</body>
</html>
Any help would be much appreciated! Thanks in advance.

How to export a python-highcharts chart for use in flask or django?

It's really all in the question but I'm using python-highcharts to build something like this jsfiddle example for inclusion in a Python Flask app. I can get it to work in the Jupyter notebook from where I can save it to an html file or export it as an iframe or div code block. But I can't get any of these to work in the flask html page. The inclusion block in the flask page looks like:
<p>
{% if result != None %}
<div id="my-chart"></div>
<script type="text/javascript">
{{result|safe}}
</script>
{% endif %}
</p>
and the relevant header parts:
<script src="//code.highcharts.com/stock/highstock.js"></script>
<script src="//code.highcharts.com/highcharts-more.js"></script>
<script src="//code.highcharts.com/modules/exporting.js"></script>
I've managed to get it working with pandas-highcharts but in this way I can't send tooltip formatting javascript functions via the dict-to-json-to-browser path... so a solution to either issue would be great.
J.
First off:
Writing JS functions in the HTML can (almost) always be prevented!
One of the first principles you should stick to is to separate your static files. More on that here.
You should only pass the variable into your script using Jinja2/DjangoTemplatingLanguage tags like this, and write all your javascript functionality in your separate .js file, which is then imported along with other scripts, by your example:
<script src="//code.highcharts.com/stock/highstock.js"></script>
<script src="//code.highcharts.com/highcharts-more.js"></script>
<script src="//code.highcharts.com/modules/exporting.js"></script>
<script src="{{ static_url }}/js/my-highstock-project.js"></script>
This way you have nice code separation and it is also (somewhat) more safe.
Which leads us to the problem at hand; importing...
So secondly:
HighCharts needs jQuery to be implemented before it can work. That is probably your problem.
To import jQuery include this to your header:
<script src="https://code.jquery.com/jquery-3.1.1.js"></script>

Apply different stylesheets to different elements of a template

I am embedding a bokeh chart in a Flask template. The app uses a master stylesheet, while the chart needs its own styles.
The master stylesheet leaks into the chart and changes its appearance. How do I apply different styles to different sections in a template so that only one style is active?
See my question on the Bokeh mailing list for more code and images.
This is the code of the template that pulls in the chart object. resources, script, and div are the elements of the object, generated by the charting library.
{% extends "base.html" %}
{% block content %}
<frame>
<head>
<meta charset='utf-8' />
<meta http-equiv='content-type' content='text/html; charset=utf-8' />
{{ resources|indent(4)|safe }}
{{ script|indent(4)|safe }}
</head>
<body>
{{ div|indent(4)|safe }}
</body>
</frame>
{% endblock %}
You don't, that's not how HTML/CSS works. All linked stylesheets apply to the entire document, Jinja templates don't factor into it. You use selectors to selectively apply CSS rules to HTML elements. Give the chart element an id, and write rules for that id.
<div id='my_chart'></div>
#my_chart {
}

Python/Tornado - compressing static files

For django projects there is an awesome tool called django-compressor. It combines all js or css files under compress template tag into single cached file, like this:
{% load compress %}
{% compress css %}
<link rel="stylesheet" href="/static/css/one.css" type="text/css" charset="utf-8">
<style type="text/css">p { border:5px solid green;}</style>
<link rel="stylesheet" href="/static/css/two.css" type="text/css" charset="utf-8">
{% endcompress %}
I'm wondering if there is anything like this for tornado projects? Or maybe any workaround/alternative solution?
I've found this project on github, but it's no longer maintained.
Take a look at tornado_utils, it should do what you want. Especially take look at tornado_static.py
tornado_static is a module for displaying static resources in a Tornado web
application.
It can take care of merging, compressing and giving URLs ideal renamings
suitable for aggressive HTTP caching.
The best option I've seen so far is WebAssets.
From the documentation:
webassets is a general, dependency-independent library for managing
the assets of your web application. It can merge and compress your CSS
and JavaScript files, supporting a wide variety of different filters,
and supports working with compilers like CoffeeScript or Sass.
You can use it in standalone mode with tornado (see the specific documentation).
Set up is easy and pretty straightforward:
from webassets import Environment
static_directory = "../static"
output_directory = "/static"
my_env = Environment(static_directory, output_directory)
Of course you can customise it far better. The rest is pretty well explained in the documentation.
Main features:
Easy integration
Possible to compress static files in advance (command-line tool)
Possible to compress static files on the fly
Supports most minifying/compression libraries (JS, CSS)
Supports LESS/SASS compiling inside the browser
Supports compression of JS Templates inside the browser (Handlebars...)
Supports CSS sprite mapper
Example of what a template (here, Jinja2) looks like after proper configuration:
# css
{% assets filters="cssmin", output="css/compiled-layout.css",
"css/custom.css",
"css/bootstrap-datepicker.css",
"css/typeahead.css" %}
<link rel="stylesheet" type="text/css" href="{{ ASSET_URL }}">
{% endassets %}
# js
{% assets filters="jsmin", output="js/lib/compiled-libs.js",
"js/lib/jquery-2.1.1.min.js",
"js/lib/jquery-ui.min.js",
"js/lib/bootstrap.min.js",
"js/lib/bootstrap-datepicker.js",
"js/lib/d3.min.js",
"js/lib/typeahead.bundle.min.js",
"js/lib/moment.min.js",
"js/lib/handlebars-v2.0.0.js",
"js/global.js" %}
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
{% endassets %}
I've been using WebAssets tied to Flask for a year with no hassle and it's perfectly reliable, plus well-maintained: it's been there for several years, and last commit to date was yesterday.
As far as I understand from looking into the open-source tornado projects there is no standard and canonical way of doing static-files minification and compression in the "tornado world".
The different options I've seen, are:
tornado_utils (see the other answer)
a fresh torminify module
Douglas Crockford's jsmin.c port to python, see:
jsmin.py
a Python port of the YUI CSS compressor:
csscompressor
cssmin.py
slimit.minify() of the slimit javascript parser
Only the first two options are tornado-specific. Other tools need to be tied up with Tornado template rendering and static files serving mechanisms manually.

How would I modify jinja2 to keep CSS and JavaScript with the corresponding HTML in included files?

This is my first question ever on SO and I'm happy to take any tips on improving. Be gentle :)
To increase maintainability, I am trying to keep CSS, JS and HTML all together in the same file. This becomes difficult with include files, or macros, etc. The final output template.render() should grab all that CSS and JS, and place it at the top and bottom of the base HTML template.
Example should explain what I mean:
base.html
<html>
<head>
<style>
{{ print_css() }}
</style>
</head>
<body>
{% include 'bolded_text.html' %}
<script>
{{ print_js() }}
</script>
</body>
</html>
bolded_text.html
{# this doesn't need to be a filter. It could be a block, or anything else that would make this work #}
{% filter add_css %}
strong {
background: #ccc;
}
{% endfilter %}
<strong>Bolded text</strong>
{% filter add_js %}
alert('javascript included!');
{% endfilter %}
Output would of course be:
<html>
<head>
<style>
strong {
background: #ccc;
}
</style>
</head>
<body>
{% include 'bolded_text.html' %}
<script>
alert('javascript included!')
</script>
</body>
</html>
Predictably, the problem is that print_css() outputs nothing.
I tried doing this with context filters, where add_js and add_css append to a variable in the context, and then print_css and print_js output that variable. This works nicely and simply for JavaScript, since the print statement follows all the filters.
However, I can't think of a way to make it work with CSS. If I could make the print_css() call lazy, or swap in the output in the jinja2 AST somehow, that might work. I'm trying to avoid hacky string manipulation (such as outputting the CSS at the bottom and then using regexes to move it to the top).
I figured there might be a way to do this elegantly and my experience with jinja2's low-level API is limited.
Any help is much appreciated, thanks!
Macros will do that, but I don't see the point why you wouldn't use StyleSheets, this enables the browser a way better caching and it's also easier to maintain.
EDIT:
Example:
{% macro generate_css(strong_bg='#ccc', additional_options=None) -%}
strong {
background: {{ strong_bg }};
}
{%- endmacro %}
<head>
<style>
{{ generate_css() }}
</style>
</head>

Categories