I'm having an issue with the font incorrectly displaying on my graph until after the user interacts with the graph on my standalone HTML document.
Here's the python code that is used to generate the script and div to place in the HTML file (notice I am using Roboto as my font):
df1 = pd.DataFrame({"A":[1,2,3,4,5,6],
"B":[5,6,3,2,1,4]})
graph = ColumnDataSource(data= df1)
p = figure(plot_width=600, plot_height=400)
p.line(source = graph, x = 'A', y = 'B')
p.xaxis.axis_label = "Number"
p.xaxis.axis_label_text_font = 'Roboto'
p.xaxis.axis_label_text_font_size = '14pt'
p.xaxis.major_label_text_font_size = '10pt'
p.yaxis.axis_label = "Average"
p.yaxis.axis_label_text_font = 'Roboto'
p.yaxis.axis_label_text_font_size = '14pt'
p.yaxis.major_label_text_font_size = '10pt'
script, div = components(p)
And the following is the html after inserting both the script, div, and the necessary other scripts and links to the header (ie the cdn.bokeh.org and fonts.googleapis):
<html lang="en">
<head>
<meta charset="utf-8">
<title>Bokeh Line Plot</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,500,700" />
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-1.4.0.min.js"></script>
<script type="text/javascript">
(function() {
var fn = function() {
Bokeh.safely(function() {
(function(root) {
function embed_document(root) {
var docs_json = '{"acd6be22-a352-429f-bbb6-e0e40d198ca6":{"roots":{"references":[{"attributes":{"callback":null},"id":"5824","type":"DataRange1d"},{"attributes":{"source":{"id":"5822","type":"ColumnDataSource"}},"id":"5859","type":"CDSView"},{"attributes":{},"id":"5847","type":"HelpTool"},{"attributes":{"dimension":1,"ticker":{"id":"5838","type":"BasicTicker"}},"id":"5841","type":"Grid"},{"attributes":{"below":[{"id":"5832","type":"LinearAxis"}],"center":[{"id":"5836","type":"Grid"},{"id":"5841","type":"Grid"}],"left":[{"id":"5837","type":"LinearAxis"}],"plot_height":400,"renderers":[{"id":"5858","type":"GlyphRenderer"}],"title":{"id":"5861","type":"Title"},"toolbar":{"id":"5848","type":"Toolbar"},"x_range":{"id":"5824","type":"DataRange1d"},"x_scale":{"id":"5828","type":"LinearScale"},"y_range":{"id":"5826","type":"DataRange1d"},"y_scale":{"id":"5830","type":"LinearScale"}},"id":"5823","subtype":"Figure","type":"Plot"},{"attributes":{"line_alpha":0.1,"line_color":"#1f77b4","x":{"field":"A"},"y":{"field":"B"}},"id":"5857","type":"Line"},{"attributes":{},"id":"5846","type":"ResetTool"},{"attributes":{},"id":"5833","type":"BasicTicker"},{"attributes":{"line_color":"#1f77b4","x":{"field":"A"},"y":{"field":"B"}},"id":"5856","type":"Line"},{"attributes":{"callback":null,"data":{"A":[1,2,3,4,5,6],"B":[5,6,3,2,1,4],"index":[0,1,2,3,4,5]},"selected":{"id":"5867","type":"Selection"},"selection_policy":{"id":"5868","type":"UnionRenderers"}},"id":"5822","type":"ColumnDataSource"},{"attributes":{"axis_label":"Average","axis_label_text_font":"Roboto","axis_label_text_font_size":{"value":"14pt"},"formatter":{"id":"5862","type":"BasicTickFormatter"},"major_label_text_font_size":{"value":"10pt"},"ticker":{"id":"5838","type":"BasicTicker"}},"id":"5837","type":"LinearAxis"},{"attributes":{"data_source":{"id":"5822","type":"ColumnDataSource"},"glyph":{"id":"5856","type":"Line"},"hover_glyph":null,"muted_glyph":null,"nonselection_glyph":{"id":"5857","type":"Line"},"selection_glyph":null,"view":{"id":"5859","type":"CDSView"}},"id":"5858","type":"GlyphRenderer"},{"attributes":{"bottom_units":"screen","fill_alpha":{"value":0.5},"fill_color":{"value":"lightgrey"},"left_units":"screen","level":"overlay","line_alpha":{"value":1.0},"line_color":{"value":"black"},"line_dash":[4,4],"line_width":{"value":2},"render_mode":"css","right_units":"screen","top_units":"screen"},"id":"5866","type":"BoxAnnotation"},{"attributes":{},"id":"5843","type":"WheelZoomTool"},{"attributes":{"overlay":{"id":"5866","type":"BoxAnnotation"}},"id":"5844","type":"BoxZoomTool"},{"attributes":{},"id":"5842","type":"PanTool"},{"attributes":{},"id":"5867","type":"Selection"},{"attributes":{},"id":"5862","type":"BasicTickFormatter"},{"attributes":{"callback":null},"id":"5826","type":"DataRange1d"},{"attributes":{},"id":"5864","type":"BasicTickFormatter"},{"attributes":{"text":""},"id":"5861","type":"Title"},{"attributes":{"ticker":{"id":"5833","type":"BasicTicker"}},"id":"5836","type":"Grid"},{"attributes":{"axis_label":"Number","axis_label_text_font":"Roboto","axis_label_text_font_size":{"value":"14pt"},"formatter":{"id":"5864","type":"BasicTickFormatter"},"major_label_text_font_size":{"value":"10pt"},"ticker":{"id":"5833","type":"BasicTicker"}},"id":"5832","type":"LinearAxis"},{"attributes":{},"id":"5828","type":"LinearScale"},{"attributes":{},"id":"5838","type":"BasicTicker"},{"attributes":{},"id":"5830","type":"LinearScale"},{"attributes":{},"id":"5868","type":"UnionRenderers"},{"attributes":{},"id":"5845","type":"SaveTool"},{"attributes":{"active_drag":"auto","active_inspect":"auto","active_multi":null,"active_scroll":"auto","active_tap":"auto","tools":[{"id":"5842","type":"PanTool"},{"id":"5843","type":"WheelZoomTool"},{"id":"5844","type":"BoxZoomTool"},{"id":"5845","type":"SaveTool"},{"id":"5846","type":"ResetTool"},{"id":"5847","type":"HelpTool"}]},"id":"5848","type":"Toolbar"}],"root_ids":["5823"]},"title":"Bokeh Application","version":"1.4.0"}}';
var render_items = [{"docid":"acd6be22-a352-429f-bbb6-e0e40d198ca6","roots":{"5823":"03d9974b-b67c-4395-9dec-d23214a6cb55"}}];
root.Bokeh.embed.embed_items(docs_json, render_items);
}
if (root.Bokeh !== undefined) {
embed_document(root);
} else {
var attempts = 0;
var timer = setInterval(function(root) {
if (root.Bokeh !== undefined) {
clearInterval(timer);
embed_document(root);
} else {
attempts++;
if (attempts > 100) {
clearInterval(timer);
console.log("Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing");
}
}
}, 10, root)
}
})(window);
});
};
if (document.readyState != "loading") fn();
else document.addEventListener("DOMContentLoaded", fn);
})();
</script>
</head>
<body>
<div class="bk-root" id="03d9974b-b67c-4395-9dec-d23214a6cb55" data-root-id="5823"></div>
</body>
</html>
Notice the font of the major axis labels, then drag the graph in any direction, you will notice the fonts for the major axis change to Roboto.
I've tried also to use autoload_static() method to generate the script, then insert the glyph into the HTML that way however, I end up with the exact same result. There are also no errors in the console on chrome.
Thanks for your help!
I had hoped things might fare better with the newer json_item API, but that does not work either. As of Bokeh 1.4 I am afraid I don't have any good answer or workaround to suggest. At this point I would characterize this as a bug that requires investigation, so I'd encourage you to submit a GitHub issue about it (including complete code to reproduce).
I've implemented a Website with a geolocation function and Button.
This Webpage gets displayed fine in a QwebEngineView (OSM Map too).
The Webpage is loaded
def __init__(self, parent=None):
super(MainGUI, self).__init__(parent)
self.ui = uic.loadUi("GPS.ui", self)
self.ui.w3View.load(QtCore.QUrl('file:///Map.html'))
All native OpenLayers Buttons (Zoom IN and OUT) are working fine.
I created a new custom button to display my geolocation on the OpenLayers Map.
This is the function im using to geolocate me:
var handleGeolocation = function() {
var coordinates;
var geolocation = new ol.Geolocation({
projection: view.getProjection(),
tracking: true
});
// handle geolocation error.
geolocation.on('error', function (error) {
var info = document.getElementById('info');
info.innerHTML = error.message;
info.style.display = '';
});
var accuracyFeature = new ol.Feature();
geolocation.on('change:accuracyGeometry', function () {
accuracyFeature.setGeometry(geolocation.getAccuracyGeometry());
});
var positionFeature = new ol.Feature();
positionFeature.setStyle(new ol.style.Style({
image: new ol.style.Circle({
radius: 6,
fill: new ol.style.Fill({
color: '#3399CC'
}),
stroke: new ol.style.Stroke({
color: '#fff',
width: 2
})
})
}));
geolocation.once('change:position', function () {
coordinates = geolocation.getPosition();
positionFeature.setGeometry(coordinates ?
new ol.geom.Point(coordinates) : null);
map.getView().setCenter(coordinates);
map.getView().setZoom(17);
});
new ol.layer.Vector({
map: map,
source: new ol.source.Vector({
features: [accuracyFeature, positionFeature]
})
});
}
I created the Button with the help from here.
the whole Webpage looks like this:
<!DOCTYPE html>
<html>
<head>
<title>Accessible Map</title>
<link rel="stylesheet" href="https://openlayers.org/en/v4.2.0/css/ol.css" type="text/css">
<!-- The line below is only needed for old environments like Internet Explorer and Android 4.x -->
<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL"></script>
<script src="https://openlayers.org/en/v4.2.0/build/ol-debug.js"></script>
<style>
a.skiplink {
position: absolute;
clip: rect(1px, 1px, 1px, 1px);
padding: 0;
border: 0;
height: 1px;
width: 1px;
overflow: hidden;
}
a.skiplink:focus {
clip: auto;
height: auto;
width: auto;
background-color: #fff;
padding: 0.3em;
}
#map:focus {
outline: #4A74A8 solid 0.15em;
}
map{
max-width: 760 px;
max-height: 50 px;
}
.geoButton {
top: 80px;
left: .5em;
}
</style>
</head>
<body>
<div id="map" class="map" tabindex="0"></div>
<script>
window.app = {};
var app = window.app;
view = new ol.View({
center: [0, 0],
zoom: 2
});
app.getLocation = function(opt_options) {
var options = opt_options || {};
var geoButton = document.createElement('button');
geoButton.innerHTML = 'L';
var handleGeolocation = function() {
/* var isMobile = {
Android: function () {
return navigator.userAgent.match(/Android/i);
},
BlackBerry: function () {
return navigator.userAgent.match(/BlackBerry/i);
},
iOS: function () {
return navigator.userAgent.match(/iPhone|iPod|iPad/i);
},
Opera: function () {
return navigator.userAgent.match(/Opera Mini/i);
},
Windows: function () {
return navigator.userAgent.match(/IEMobile/i);
},
any: function () {
return ((isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Opera() || isMobile.Windows()));
}
};
if (isMobile.any()){
geolocation.setTrackingOptions(enableHighAccuracy );
} */
var coordinates;
var geolocation = new ol.Geolocation({
projection: view.getProjection(),
tracking: true
});
// handle geolocation error.
geolocation.on('error', function (error) {
var info = document.getElementById('info');
info.innerHTML = error.message;
info.style.display = '';
});
var accuracyFeature = new ol.Feature();
geolocation.on('change:accuracyGeometry', function () {
accuracyFeature.setGeometry(geolocation.getAccuracyGeometry());
});
var positionFeature = new ol.Feature();
positionFeature.setStyle(new ol.style.Style({
image: new ol.style.Circle({
radius: 6,
fill: new ol.style.Fill({
color: '#3399CC'
}),
stroke: new ol.style.Stroke({
color: '#fff',
width: 2
})
})
}));
geolocation.once('change:position', function () {
coordinates = geolocation.getPosition();
positionFeature.setGeometry(coordinates ?
new ol.geom.Point(coordinates) : null);
map.getView().setCenter(coordinates);
map.getView().setZoom(17);
});
new ol.layer.Vector({
map: map,
source: new ol.source.Vector({
features: [accuracyFeature, positionFeature]
})
});
}
geoButton.addEventListener('click', handleGeolocation, false);
geoButton.addEventListener('touchstart', handleGeolocation, false);
var element = document.createElement('div');
element.className = 'ol-unselectable ol-control geoButton';
element.appendChild(geoButton);
ol.control.Control.call(this, {
element: element,
target: options.target
});
};
ol.inherits(app.getLocation, ol.control.Control);
//Standard Initialisierung
// Geolocation function
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
target: 'map',
controls: ol.control.defaults({
attributionOptions: /** #type {olx.control.AttributionOptions} */ ({
collapsible: false
})
}).extend([new app.getLocation()]),
view: view
});
//Display Input Datastream
</script>
</body>
</html>
Inside a normal browser it's working fine but not inside my PyQt app.
After clicking the custom Button nothing happens.
What am i doing wrong or is not possible?
The main problem is to enable the permissions, if you run in a browser like Firefox, Chrome, etc. will show you a popup asking you to accept or not the GeoLocation permission.
In this case it must be enabled by code, for this the QWebEnginePage emits a signal every time authorization is required, it does this through the signal featurePermissionRequested, we connect it to some slot and we enable the permission with the function setFeaturePermission().
self.ui.w3View..page().featurePermissionRequested.connect(self.onFeaturePermissionRequested)
def onFeaturePermissionRequested(self, securityOrigin, feature):
self.sender().setFeaturePermission(securityOrigin,
QWebEnginePage.Geolocation,
QWebEnginePage.PermissionGrantedByUser)
Note: On Linux I still experience problems with the Geoclue provider, the error message reads as follows:
Failed to set Geoclue positioning requirements. Geoclue error:
org.qtproject.QtDBus.Error.InvalidObjectPath
Adding the following lines solved my Problems:
self.ui.w3View.page().featurePermissionRequested.connect(self.permissionRequested)
def permissionRequested(self, frame, feature):
self.ui.w3View.page().setFeaturePermission(frame, feature, QtWebEngineWidgets.QWebEnginePage.PermissionGrantedByUser)
Found it in this post and editing it to PyQt 5.9.
my file temp.py read data from my sensor connected to my rasbperry . my views sends it to html file . I think my call in index.html is not correct . Because when I run my Django project it returns a blank page
views.py
from django.shortcuts import render
from temp import get_temp
import json
def index(request):
return render(request, 'aps/index.html', {'t' : get_temp()})
temp.py
def get_temp() :
tfile = open("/sys/bus/w1/devices/28-0000075292ed/w1_slave")
text = tfile.read()
tfile.close()
secondline = text.split("\n")[1]
temperaturedata = secondline.split(" ")[9]
temperature = float(temperaturedata[2:])
temperature = temperature / 1000
return temperature
index.html
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title> Temperature Sensor</title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<style type="text/css">
${demo.css}
</style>
<script type="text/javascript">
$(function () {
$(document).ready(function () {
Highcharts.setOptions({
global: {
useUTC: false
}
});
$('#container').highcharts({
chart: {
type: 'spline',
animation: Highcharts.svg, // don't animate in old IE
marginRight: 10,
events: {
load: function () {
// set up the updating of the chart each second
var series = this.series[0];
setInterval(function () {
var x = (new Date()).getTime(), // current time
y = {{ t }} ;
series.addPoint([x, y], true, true);
}, 3000);
}
}
},
title: {
text: 'Live sensor temperature data'
},
xAxis: {
type: 'datetime',
tickPixelInterval: 150
},
yAxis: {
title: {
text: 'Value'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
tooltip: {
formatter: function () {
return '<b>' + this.series.name + '</b><br/>' +
Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', this.x) + '<br/>' +
Highcharts.numberFormat(this.y, 2);
}
},
legend: {
enabled: false
},
exporting: {
enabled: false
},
series: [{
name: 'sensor data',
data: (function () {
var data = [],
time = (new Date()).getTime(),
i;
for (i = -19; i <= 0; i += 1) {
data.push({
x: time + i * 1000,
y: {{ t }}
});
}
return data;
}())
}]
});
});
});
</script>
</head>
<body>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<div id="container" style="min-width: 310px; height: 400px; margin: 0 auto"></div>
</body>
</html>
Add your urls.py
What url are you using at the browser?
If possible add what give you back the browser when you press cntrl+u in your blank page.
I am using code from this github project to create a python flask application with d3js charts. The templates/index.html file contains css and js code written in the HTML file. But, if I try to put that code in external files and reference that in my index.html, the file is untraceable. I tried different paths (templates folder and also the root folder) but none of them worked.
Please suggest on how I should use external css and js files.
This is my templates/index.html code:
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>flask+d3 Hello World</title>
<script src="http://d3js.org/d3.v2.js"></script>
<link rel="stylesheet" type="text/css" href="mystyle.css">
<link rel="stylesheet" type="text/css" href="templates/mystyle.css">
<link rel="stylesheet" type="text/css" href="../mystyle.css">
</head>
<body>
<h1>Hello World using d3.js & Flask</h1>
<div id="info">
<div id="point-info">
Click on a point.
</div>
</div>
<div id="plot">
</div>
<script>
// Set up the plot window.
var margin = 80;
var w = 700 - 2 * margin, h = 500 - 2 * margin;
var svg = d3.select("#plot").append("svg")
.attr("width", w + 2 * margin)
.attr("height", h + 2 * margin)
.append("svg:g")
.attr("transform", "translate(" + margin + ", " + margin + ")");
// The colorbar.
var color = d3.scale.quantize()
.range(["#156b87", "#876315", "#543510", "#872815"])
.domain([0, 1]);
// Axes scaling functions.
var xscale = d3.scale.linear().range([0, w]);
var yscale = d3.scale.linear().range([h, 0]);
// The axes objects themselves.
var xaxis = d3.svg.axis().scale(xscale).ticks(8);
var yaxis = d3.svg.axis().scale(yscale).ticks(8).orient("left");
svg.append("svg:g").attr("class", "x axis")
.attr("transform", "translate(0, " + h + ")");
svg.append("svg:g").attr("class", "y axis");
// Show the information about a particular point.
var show_info = function (d) {
d3.select("#point-info").text("This is point " + d._id + ". "
+ "It has the coordinates (" + d.x + ", " + d.y + ").");
};
// Load the data.
var callback = function (data) {
// Rescale the axes.
xscale.domain([d3.min(data, function (d) { return d.x; }) - 0.05,
d3.max(data, function (d) { return d.x; }) + 0.05]);
yscale.domain([d3.min(data, function (d) { return d.y; }) - 0.05,
d3.max(data, function (d) { return d.y; }) + 0.05]);
// Display the axes.
svg.select(".x.axis").call(xaxis);
svg.select(".y.axis").call(yaxis);
// Insert the data points.
svg.selectAll("circle").data(data).enter()
.append("circle")
.attr("id", function (d) { return d._id; })
.attr("cx", function (d) { return xscale(d.x); })
.attr("cy", function (d) { return yscale(d.y); })
.attr("r", function (d) { return 2 * Math.sqrt(d.area); })
.style("fill", function (d) { return color(d.color); })
.on("mousedown", show_info);
};
d3.json("/data", callback);
</script>
</body>
</html>
This is my mystyle.css code:
path.line {
fill: none;
stroke: #666;
stroke-width: 1.5px;
}
.domain {
stroke-width: 1px;
}
circle {
cursor: pointer;
}
.axis {
shape-rendering: crispEdges;
}
.axis line, .axis path {
stroke-width: 1px;
stroke: #000;
fill: none;
}
.tooltip {
display: none;
}
.tooltip.active {
display: block;
}
.tooltip rect {
fill: #ff0000;
}
Simple answer is: create a folder named 'static', place your static files in it and their url path in HTML is '/static/your_file_path/your_file_name.extension'.
Here is the documenation on static file where you can find the authentic answer.
If you would like to change the default 'static' folder and also change default static file url path, you can read these application startup configurations