Related
I've written a python script to get data from Google Search Console, stores it etc etc and print out an html output. The whole thing works really well and I've used buttons to select different datasets to hide/show them as you click on them.
I have no idea how to initialise the chart with index[0] though, all datasets are being rendered and shown when the page is loaded. I've had a look through the documentation but this is way over my head. Is there something in the options I can call to just show one dataset right from the start?
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<div class="m-5">
<div class="card col-md-6 offset-md-3">
<canvas id="myChart" ></canvas>
</div>
</div>
<div class="listSelector">
<ul>
<button onclick="toggleData(0)">https://www.somewebsite.co.uk/</button><br>
<button onclick="toggleData(1)">https://www.somewebsite.co.uk/blog/</button><br>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.6.0/chart.min.js"></script><script>const ctx = document.getElementById('myChart').getContext('2d');const myChart = new Chart(ctx,
{type:"line",data:{labels:['2022-07-16', '2022-07-17', '2022-07-18', '2022-07-19', '2022-07-20', '2022-07-21', '2022-07-22', '2022-07-23', '2022-07-24', '2022-07-25', '2022-07-26', '2022-07-27', '2022-07-28', '2022-07-29', '2022-07-30', '2022-07-31', '2022-08-01', '2022-08-02', '2022-08-03', '2022-08-04', '2022-08-05', '2022-08-06', '2022-08-07', '2022-08-08', '2022-08-09', '2022-08-10', '2022-08-11', '2022-08-12', '2022-08-13', '2022-08-14', '2022-08-15', '2022-08-16', '2022-08-17', '2022-08-18', '2022-08-19', '2022-08-20', '2022-08-21', '2022-08-22', '2022-08-23', '2022-08-24', '2022-08-25', '2022-08-26', '2022-08-27', '2022-08-28', '2022-08-29', '2022-08-30', '2022-08-31', '2022-09-01', '2022-09-02', '2022-09-03', '2022-09-04', '2022-09-05', '2022-09-06', '2022-09-07', '2022-09-08', '2022-09-09', '2022-09-10', '2022-09-11', '2022-09-12', '2022-09-13', '2022-09-14', '2022-09-15', '2022-09-16', '2022-09-17', '2022-09-18', '2022-09-19', '2022-09-20', '2022-09-21', '2022-09-22', '2022-09-23', '2022-09-24', '2022-09-25', '2022-09-26', '2022-09-27', '2022-09-28', '2022-09-29', '2022-09-30', '2022-10-01', '2022-10-02', '2022-10-03', '2022-10-04', '2022-10-05', '2022-10-06', '2022-10-07', '2022-10-08', '2022-10-09', '2022-10-10', '2022-10-11', '2022-10-12', '2022-10-13', '2022-10-14', '2022-10-15', '2022-10-16', '2022-10-17', '2022-10-18', '2022-10-19', '2022-10-20', '2022-10-21', '2022-10-22', '2022-10-23'],datasets: [
{label: "https://www.somewebsite.co.uk/", data: [4551, 5072, 5426, 5224, 4672, 4257, 4035, 4376, 4680, 4916, 4957, 4929, 4786, 5391, 5390, 5991, 5463, 5308, 4739, 4450, 4577, 4831, 5045, 5006, 4609, 4098, 3720, 4300, 5185, 5251, 4503, 3757, 3971, 3967, 3772, 3619, 3585, 3601, 3485, 3454, 3497, 3431, 3602, 3732, 4574, 4470, 4393, 3541, 3397, 3458, 3564, 3823, 3897, 3682, 3158, 3081, 3395, 4089, 4502, 4664, 4866, 4398, 4098, 3845, 4018, 4149, 4272, 4324, 4285, 4085, 4403, 4754, 5957, 6702, 7324, 7109, 7209, 7477, 7800, 7785, 7639, 7195, 6739, 6729, 7143, 7481, 7313, 6630, 6127, 5847, 6239, 6811, 7285, 7335, 7139, 6941, 6663, 6233, 4054, 1937],fill: "start", backgroundColor: ['rgba(90, 204, 204,0.4)'], borderColor: ['rgba(90, 204, 204, 1)'], borderWidth: 2 },
{label: "https://www.somewebsite.co.uk/blog/", data: [75, 88, 123, 116, 92, 62, 39, 59, 87, 90, 83, 55, 53, 37, 51, 77, 99, 83, 61, 41, 32, 30, 35, 35, 34, 28, 30, 21, 20, 17, 32, 40, 43, 38, 29, 33, 33, 47, 56, 49, 34, 17, 14, 19, 23, 31, 25, 17, 7, 17, 28, 39, 57, 55, 47, 21, 20, 22, 20, 22, 26, 29, 22, 21, 26, 48, 62, 63, 47, 35, 33, 33, 30, 32, 36, 37, 29, 27, 21, 22, 21, 24, 33, 25, 37, 35, 44, 34, 29, 20, 13, 23, 44, 52, 42, 32, 32, 27, 13, 2],fill: "start", backgroundColor: ['rgba(90, 204, 204,0.4)'], borderColor: ['rgba(90, 204, 204, 1)'], borderWidth: 2 },
]},options: {
plugins: {
legend: {
display:false
}
},
scales: {
y: {
beginAtZero: true
}}}});
function toggleData(value) {
const showValue = myChart.isDatasetVisible(value)
if(showValue === true) {
myChart.hide(value);
}
if(showValue === false) {
myChart.show(value);
}
}
</script>
My script can produce hundreds of datasets, I've shortened it to 2 here because of the size of the label and data arrays.
I'm missing a function or method call. I would like the very first dataset to be shown, then as I click on different buttons the chart to refresh. I think I can do that, I'm just looking for the initialisation of the chart.
We have a custom zio.test.Assertion that wrap json-path-assert:
def isJson(matching: org.hamcrest.Matcher[_ >: ReadContext]): Assertion[HttpEntity] = {
def test(entity: => HttpEntity): Boolean = {
// Removed for brevity
}
Assertion.assertion[HttpEntity]("isJson")(param(matching))(test)
}
We are quite happy with it but the failure message is far to be obvious:
response.body = Strict(ByteString(121, 32, 95, 111, 10, 108, 113, 35, 50, 90, 124, 23, 112, 111, 112, 31, 48, 24, 46, 31, 111, 22, 111, 25, 93, 52, 41, 54, 59, 90, 100, 43, 42, 51, 75, 14, 41, 54, 40, 65, 34, 42, 99, 88, 100, 54, 34, 25, 33, 89, 41, 40, 54, 52, 44, 40, 31, 101, 112, 105, 91, 10, 35, 125, 79, 106, 95, 11, 11, 32, 85, 13, 43, 104, 111)... and [661] more,Some(application/json)) did not satisfy isJson(with json path "$['store']['name']")
I would like to print the Json string decoded from those bytes but I do not see how to do that.
How can we customize the messages of a custom zio.test.Assertion?
Thanks
The param(matching) means that you are using the toString method of matching to render the the input of the assertion.
You can pass the decoded json string instead to have that display. For example (assuming your json is UTF-8 encoded):
Assertion.assertion[HttpEntity.Strict]("isJson")
(param(matching.data.decodeString(StandardCharsets.UTF_8))(test)
That particular example only works on HttpEntity.Strict but can be generalized to HttpEntity if you access the entity contents with .dataStream
I know this question has been asked a fair bit on here, but the solution that's been going around hasn't been working for me.
My chart renders in real time based on the start/end dates provided on the front-end (HTML date input widget). Since the default start time for that widget is 01/01/2019, charts.js will create a chart for the 01/01/2019 start/end times, and then proceed to produce the chart for the specified start/end dates. The 01/01/2019 chart shows on hover and I'd like to get rid of it.
function dayChart(labels_day, data_day) {
var ctx_day = document.getElementById('day-chart').getContext('2d');
var config = {
type: 'bar',
data: {
labels: labels_day,
// labels: ['Early Morning (00:00-05:59)', 'Morning (06:00-11:59)', 'Afternoon (12:00-18:59)', 'Night (19:00-23:59)'],
datasets: [{
label: '# of Orders by Day of the Week',
data: data_day,
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)',
'rgba(255, 99, 132, 0.2)',
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)',
'rgba(255, 99, 132, 1)',
],
borderWidth: 1
}]
},
options: {
responsive: true,
title: {
display: true,
text: 'Taxi Orders calculated by day of the week'
},
scales: {
yAxes: [{
id: data_day,
display: true,
ticks: {
stepsize: 500,
min: 0,
}
}]
},
}
}
var chart_day = new Chart (ctx_day, config)
if (chart_day) {
chart_day.destroy();
chart_day = new Chart (ctx_day, config);
chart_day.update();
}
}
form section of html file
<form name="date-input" method="POST" action="/date-input/">
<label for="start">Start date:</label>
<input type="date" id="start" name="start_date" value="2019-01-01" min="2019-01-01" max="2019-06-30">
<label for="end">End date:</label>
<input type="date" id="end" name="end_date" value="2019-01-01" min="2019-01-01" max="2019-07-01">
</form>
async call for start/end dates
<script src="https://code.jquery.com/jquery-3.5.1.js"></script>
<script>
// global variables - so that chartjs doesn't show old data on hover
var chart_day;
var chart_hour;
var chart_payment;
var start_date = Date.parse($("#start").val()) / 1000; // const can't be re-assigned or redeclared. Date() to convert datetime into epoch time
var end_date = Date.parse($("#end").val()) / 1000; // divide by 1000 to get 10 digits (compatible with values in DB)
function ajaxRequest() {
var start_date = Date.parse($("#start").val()) / 1000;
var end_date = Date.parse($("#end").val()) / 1000;
console.log(start_date)
console.log(end_date)
$.ajax({ // initialize an AJAX request
type: "POST",
url: '/get-data/', // calls data from /date-input/ endpoint
data: {
'start_date': start_date, // add the order id to the POST parameters
'end_date': end_date,
'csrfmiddlewaretoken': "{{csrf_token}}",
},
success: function (data) { // `data` is from `homepage` view function
labels_payment = data.labels_payment
data_payment = data.data_payment
labels_hour = data.labels_hour
data_hour = data.data_hour
labels_day = data.labels_day
data_day = data.data_day
// call payment, hour, and dow methods to render in the frontend
setPaymentMethodChart(labels_payment, data_payment)
hourlyChart(labels_hour, data_hour)
dayChart(labels_day, data_day)
// console.log(data)
console.log(data.start_date)
console.log(data.end_date)
console.log(data.labels_payment)
console.log(data.data_payment)
},
error: function (data, xhr, status, error) {
console.log("yikes")
}
});
}
You correctly defined chart_day globally and even commented it as follows:
global variables - so that chartjs doesn't show old data on hover
The problem however lies in your dayChart function. Instead of using the globally defined chart_day variable, you defined an identically named variable in the local scope of the function.
The solution would be to replace the following code block:
var chart_day = new Chart (ctx_day, config)
if (chart_day) {
chart_day.destroy();
chart_day = new Chart (ctx_day, config);
chart_day.update();
}
...with this one:
if (chart_day) {
chart_day.destroy();
}
chart_day = new Chart (ctx_day, config);
How to add the target line in google column chart like this.
If you'd like to combine the columnchart and linechart, use ComboChart. Documentation and examples are here :
https://developers.google.com/chart/interactive/docs/gallery/combochart
basically, have the data point for the line chart as one of the columns in the DataTable and specify this column to be the "series" = "line", whereas the other columns are visualized in a ColumnChart.
You can use a Stepped Area series to achieve this. It's a little awkward but works well.
var data = google.visualization.arrayToDataTable([
['Month', 'Bolivia', 'Ecuador', 'Madagascar', 'Papua New Guinea', 'Rwanda', ''],
['2004/05', 165, 938, 522, 998, 450, 250],
['2005/06', 135, 1120, 599, 1268, 288, 250],
['2006/07', 157, 1167, 587, 807, 397, 250],
['2007/08', 139, 1110, 615, 968, 215, 250],
['2008/09', 136, 691, 629, 1026, 366, 250]
]);
var options = {
seriesType: "line",
series: {5: {
type: "steppedArea",
color: '#FF0000',
visibleInLegend: false,
areaOpacity: 0}
}
};
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
Example
Stepped Area Google Chart Example
To avoid the ugly outline, just use: enableInteractivity: false
To make the steppedArea #Ryan suggested above a litte bit less awkward, you can setup a second (right) axis and set the base line to the value you want for the target line. The second axis will be setup for the seppedArea data. This avoids the uggly outline effect when you hover the pointer over the chart and under the line. Do something like this in the options:
var options = {
seriesType: "line",
series: {5: {
type: "steppedArea",
color: '#FF0000',
visibleInLegend: false,
areaOpacity: 0,
targetAxisIndex: 1 } //tell the series values to be shown in axe 1 bellow
},
vAxes: [ //each object in this array refers to one axe setup
{}, //axe 0 without any special configurations
{
ticks: [250], //use this if you want to show the target value
baseline: 250 //this shifts the base line to 250
}
]
};
I'm playing a bit with Google Charts API, and actually I need to change the default text showed in the tooltip of candlestick chart. Not only to change the style, but also it's content.
Does anyone knows how to achieve it?
Try this code to customize Tooltip content using html tags.
data.addRows([
['Mon', 20, 28, 38, 45, customTooltip('Monday')],
['Tue', 31, 38, 55, 66, customTooltip('Tuesday')],
['Wed', 50, 55, 77, 80, customTooltip('Wednesday')],
['Thu', 77, 77, 66, 50, customTooltip('Thursday')],
['Fri', 68, 66, 22, 15, customTooltip('Friday')]
]);
function customTooltip(text) {
return '<div style="padding:5px 5px 5px 5px;">' +
'<table id="medals_layout" style=" color:#db6acf; font-size:large">' + '<tr>' +
'<td><b>' + text + '</b></td>' + '</tr>' + '</table>' + '</div>';
}
Take a look at this jqfaq.com that has a working sample for Line chart
You can drop this into google's visualization playground:
function drawVisualization() {
data = new google.visualization.DataTable()
data.addColumn('string', 'Date');
data.addColumn('number');
data.addColumn('number');
data.addColumn('number');
data.addColumn('number');
data.addColumn({type:'string',role:'tooltip'});
data.addRow();
base = 10;
data.setValue(0, 0, 'Datapoint1');
data.setValue(0, 1, base++);
data.setValue(0, 2, base++);
data.setValue(0, 3, base++);
data.setValue(0, 4, base++);
data.setValue(0, 5, " This is my tooltip1 ");
data.addRow();
data.setValue(1, 0, 'Datapoint2');
data.setValue(1, 1, base++);
data.setValue(1, 2, base++);
data.setValue(1, 3, base++);
data.setValue(1, 4, base++);
data.setValue(1, 5, "This is my second tooltip2");
// Draw the chart.
var chart = new google.visualization.CandlestickChart(document.getElementById('visualization'));
chart.draw(data, {legend:'none', width:600, height:400});
}