Resizing a js chart in shiny app - html

I am using a gauge widget from c3 library.
It's function are composed by 3 elements:
function(Value, width, height)
When I try to generate the dashboard, the result is this one:
I am using this layout:
splitLayout(C3GaugeOutput("gauge1","auto","auto"),
C3GaugeOutput("gauge2","auto","auto"),
C3GaugeOutput("gauge3","auto","auto"))
I tryied changed the dimensions, but this side bar still appears.
The C3 code is the following:
HTMLWidgets.widget({
name: 'C3Gauge',
type: 'output',
factory: function(el, width, height) {
return {
renderValue: function(x) {
// Check if we have a reference to our chart
if(typeof(el.chart) == 'undefined'){
// create a chart and set options
// note that via the c3.js API we bind the chart to the element with id equal to chart1
var chart = c3.generate({
bindto: el,
data: {
json: x,
type: 'gauge',
},
gauge: {
label:{
//returning here the value and not the ratio
format: function(value, ratio){ return value;}
},
min: 0,
max: 100,
width: 15,
units: '%' //this is only the text for the label
}
});
el.chart = chart;
}else{
// Update the chart if it already exists
el.chart.load({json: x});
}
},
resize: function(width, height) {
// TODO: code to re-render the widget with a new size
}
};
}
});

Solved:
Using box() function:
fluidRow(box(C3GaugeOutput("gauge1","auto","auto")),
box(C3GaugeOutput("gauge2","auto","auto")),
box(C3GaugeOutput("gauge3","auto","auto")))

Related

How can we increase the fonsize of ag-grid data on context menu action?

I am using Angular 6 and ag grid version 18. I want to have an option from the context menu to increase and decrease the fontsize
I want a feature something like this. I tried rowstyle,cellstyle that did not work
Below is how the column definition looks like. Note I am using variable a for incrementing and decrementing the font size -
var a = 10;
var columnDefs = [
{headerName: 'Athlete', field: 'athlete', width: 150,
cellStyle: function(params) {
return {fontSize: params.context.a + 'px', backgroundColor: 'green'};
}
},
..
];
Set the reference to your component as below, this will be used in context menu callbacks -
var gridOptions = {
context: this,
..
};
Below is the cell refresh and context menu -
function refreshCells() {
var params = {
force: true
};
gridOptions.api.refreshCells(params);
}
function getContextMenuItems(params) {
var result = [
{
// custom item
name: 'Increase Font',
action: function() {
params.context.a = params.context.a + 5;
params.context.refreshCells();
},
},
{
// custom item
name: 'Decrease Font',
action: function() {
params.context.a = params.context.a - 5;
params.context.refreshCells();
},
}
];
return result;
}
Please see Plunkr -
Increase/decrease font ag-grid plunkr

Show bar with zero value in ChartJs v2

I'm wondering is there any way to show in ChartJs (in bar chart) bars with zero value?
I mean something like this: https://jsfiddle.net/vrg5cnk5/16/, so the second bar would be just blue border on level zero.
I used already this code:
ticks: {
beginAtZero: true,
min: 0,
suggestedMin: 0
}
but I'm not surprised it didn't work.
Thanks in advance
Simply specify minBarLength in the dataset, with the minimum length in pixels the bars should have. See documentation.
Working Example:
var $chartCanvas = $('myCanvas');
var barChart = new Chart(myCanvas, {
type: 'bar',
data: {
labels: ['Accepted Answer', 'Top rated answer', 'This Answer'],
datasets:[{
data: [0, 3, 10],
minBarLength: 7, // This is the important line!
}]
},
options: {
title: {
display: true,
text: 'helpfulness of answers to this questions'
},
legend: {
display: false
}
}
});
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<canvas id="myCanvas"></canvas>
After dig into the plugin system, if you using Chart.js >=2.5, you can write a plugin to achieve it. Here is an example to draw a line when data is zero.
Here is my code:
const zeroCompensation = {
renderZeroCompensation: function (chartInstance, d) {
// get postion info from _view
const view = d._view
const context = chartInstance.chart.ctx
// the view.x is the centeral point of the bar, so we need minus half width of the bar.
const startX = view.x - view.width / 2
// common canvas API, Check it out on MDN
context.beginPath();
// set line color, you can do more custom settings here.
context.strokeStyle = '#aaaaaa';
context.moveTo(startX, view.y);
// draw the line!
context.lineTo(startX + view.width, view.y);
// bam! you will see the lines.
context.stroke();
},
afterDatasetsDraw: function (chart, easing) {
// get data meta, we need the location info in _view property.
const meta = chart.getDatasetMeta(0)
// also you need get datasets to find which item is 0.
const dataSet = chart.config.data.datasets[0].data
meta.data.forEach((d, index) => {
// for the item which value is 0, reander a line.
if(dataSet[index] === 0) {
this.renderZeroCompensation(chart, d)
}
})
}
};
and here is how to add the plugin to Chart.js
var chart1 = new Chart(ctx, {
plugins: [zeroCompensation]
});
The offcial document is not clear about their plugin API, you may console.log to find what you want.
There is no way to configure chart.js to do this, but you could use a hack instead. Just set your value for the 0 bar to a really small number like 0.1.
data: [2, 0.1, 3, 1]
Here is an example forked from yours.
If you are using tooltips, then you would have to also add some logic so that the tooltip for that bar still displays a value of 0. You can do this using the label callback.
label: function(tooltipItem, data) {
var value = data.datasets[0].data[tooltipItem.index];
var label = data.labels[tooltipItem.index];
if (value === 0.1) {
value = 0;
}
return label + ': ' + value + ' %';
}
Here is an example putting it all together.
If you struggle with this, here's what I came up with. It is similar idea to Li Jinyao, but in addition, you would get click and hover events (tooltip) working for whole bar.
I value is close to 0 but negative, the bar will show on negative side of x axis - you can easily get rid of it if that's not what you want to do.
const zeroCompensation = {
id: 'zeroCompensation',
beforeDatasetsDraw: function(chart) {
const meta = chart.getDatasetMeta(0)
forEach(meta.data, d => {
const barHeight = d._view.base - d._view.y;
if(Math.abs(barHeight) < minBarHeight /* I used value 5 */) {
d._view.y = d._view.base - minBarHeight * (Math.sign(barHeight) || 1);
}
});
}};
and add it to plugins:
plugins: [zeroCompensation]
Keep in mind that this will work for values close to 0, not only 0. If you want it only for zeroes, you can change contents of if condition to:
chart.config.data.datasets[0].data[index] === 0
This is what Li Jinyao used in his answer.
Hope that helps.
Edit: I wanted to highlight that this solution works regardless of values spread. Answer marked as solution will not work as intended if there are some high values in data set - 0.1 will render same as 0 in that case.
Here is the simplest way to do this in V3 chart js
Chart.defaults.datasets.bar.minBarLength = 5;
2019 Update
This can be done easily as below.
var myChart = new Chart(ctx, {
...
options: {
...
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
);
You can find this in Chart.js documentation https://www.chartjs.org/docs/latest/
I just stumbled over this questions because I had a similar problem: The type of my Chart.js chart was 'horizontalBar' and for some datasets (where no zero values was present across the dataset) the horizontal bar did not start with 0 rather with the lowest value from the dataset.
I tried to figure out a solution and came up with following entry in the options object while creating the charts:
ticks: {
beginAtZero:true,
mirror:false,
suggestedMin: 0,
suggestedMax: 100
}
However that did not work as expected although all posts said it works that way.
After further investigation and reading of the Chart.js documentation I found the solution. The reason the further step did not work was following I found in the documentation:
However, any options specified on the x axis in a bar chart, are applied to the y axis in a horizontal bar chart.
So I just changed my options object to hold the proper configuration for the xAxes and it worked.
For those who are interested here is the the whole code I used for creating the horizontal bar chart with y-axis starting always at zero:
this.chart = new Chart(
ctx,
{
type: 'horizontalBar',
data: this.data.chartdata,
options: {
scales: {
xAxes: [{
stacked: false,
ticks: {
beginAtZero:true,
mirror:false,
suggestedMin: 0,
suggestedMax: 100
}
}],
yAxes: [{
stacked: true
}]
},
scaleBeginAtZero : true,
// important here to use () =>
// to keep the scope of this
onClick: (e) => {
var actChart : Chart = this.charts[trialId];
var element =
actChart.getElementAtEvent(e);
}
}
}
);

Create an average line for Google Charts

I am learning to use Google Charts and I'm trying to get an average of all values and show a line on the chart to represent the average.
Below is an of how my chart looks but I need an average line for all the values.
thanks in advance for your attention.
<html>
<body style="font-family: Arial;border: 0 none;">
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="dashboard" style="width:1300px;overflow:scroll;">
<div id="chart" style="position: relative; width: 1300px; height: 300px;"></div>
<div id="control" style="position: relative; width: 1300px; height: 30px;"></div>
</div>
<script type="text/javascript">
google.charts.load('current', {
callback: function () {
var query = new google.visualization.Query('xxxxxxx');
query.setQuery('select A,B,C,D');
query.send(function (response) {
if (response.isError()) {
console.log('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage());
return;
}
var control = new google.visualization.ControlWrapper({
controlType: 'ChartRangeFilter',
containerId: 'control',
options: {
filterColumnIndex: 0,
ui: {
chartType: 'ScatterChart',
chartOptions: {
pointSize: 2,
chartArea: {width: '90%'},
hAxis: {format: 'dd/MM/yyyy'}
},
chartView: {
columns: [ 0, 1, 2]
}
}
}
});
var chart = new google.visualization.ChartWrapper({
chartType: 'SteppedAreaChart',
containerId: 'chart',
options: {
filterColumnIndex: 0,
pointSize: 2,
chartArea: {height: '80%', 'width': '90%'},
hAxis: {format: 'E dd/MMM','textStyle':{'fontSize': 11, 'color': 'black','bold':true},'minTextSpacing': 0, 'slantedText': false},
vAxis: {format: '0'},
legend: {position: 'top'},
bar: {groupWidth: '100%'},
isStacked: false
},
view: {
columns: [ 0, 1,2]
}
});
var proxyTable = new google.visualization.ChartWrapper({
chartType: 'Table',
containerId: 'TableProxy',
options: {
page: 'enable',
pageSize: 1
},
view: {
columns: [0]
}
});
google.visualization.events.addListener(proxyTable, 'ready', function () {
var dt = proxyTable.getDataTable();
var groupedData = google.visualization.data.group(dt, [0], [{
column: 2,
type: 'number',
aggregation: google.visualization.data.avg
}]);
chart.setDataTable(groupedData);
chart.draw();
});
google.visualization.events.addListener(proxyTable, 'ready', function () {
var group = google.visualization.data.group(proxyTable.getDataTable(), [{
column: 0,
type: 'date',
modifier: function () {
return 1;
}
}], [{
column: 2,
type: 'number',
aggregation: google.visualization.data.avg
}]);
});
dashboard = new google.visualization.Dashboard(document.getElementById('dashboard'));
dashboard.bind(control, chart);
dashboard.draw(response.getDataTable());
});
},
packages: ['controls', 'corechart', 'table'], 'language': 'pt-br'
});
</script>
</body>
</html>
It's possible to group by date (code bellow)...but the main difficult thing to do is how to use the controlType: 'ChartRangeFilter'. Anyone has any idea??
function floorDate(datetime) {
var newDate = new Date(datetime);
newDate.setHours(0);
newDate.setMinutes(0);
newDate.setSeconds(0);
return newDate;
}
var columnChart1 = new google.visualization.ChartWrapper({
'chartType': 'ColumnChart',
'containerId': 'chart3'
});
// columnChart1.draw();
// Create the dashboard.
new google.visualization.Dashboard(document.getElementById('dashboard')).
// Configure & bind the controls
bind(divPicker, [table, columnChart]).
// Draw the dashboard
draw(data);
google.visualization.events.addListener(divPicker, 'ready',
function(event) {
// group the data of the filtered table and set the result in the pie chart.
columnChart1.setDataTable(google.visualization.data.group(
// get the filtered results
table.getDataTable(), [{
'column': 0,
'modifier': floorDate,
'type': 'date'
}], [{
'column': 2,
'aggregation': google.visualization.data.sum,
'type': 'number'
}]
));
// redraw the pie chart to reflect changes
columnChart1.draw();
});
google.visualization.events.addListener(divPicker, 'statechange',
function(event) {
// group the data of the filtered table and set the result in the pie chart.
columnChart1.setDataTable(google.visualization.data.group(table.getDataTable(), [0], [{
'column': 2,
'aggregation': google.visualization.data.avg,
'type': 'number'
}]));
// redraw the pie chart to reflect changes
columnChart1.draw();
});
}
google.setOnLoadCallback(drawVisualization);
</script>
You should be able to make use of a trendline.
A trendline is a line superimposed on a chart revealing the overall direction of the data. Google Charts can automatically generate trendlines for Scatter Charts, Bar Charts, Column Charts, and Line Charts.
Guessing from the given code, you may want to add trendlines: { 0: {} } to the chartOptions for your control variable.
Putting your code into a jsFiddle or a Codepen would make it easier to debug and show you a valid solution to your particular problem.
I appreciate this is a little old, but my searching found this and wanted to help further.
Adding a trendline gives a data's trend (increasing, decreasing) and not really the average. I cannot claim this answer as mine, please see https://groups.google.com/forum/#!topic/google-chart-api/UOdUFszYSRc
As Tom suggests I actually use the combo chart and compute a second series, but as your charts are quite complex you may wish to use the API method, which his JSFiddle (found in the link above) shows working - thanks Tom.

Extjs 5 Lock on grid columns

I wanted to lock the first few columns of my grid and provide horizontal scrolling for the rest of the columns. Am making use of column header gruping.
I have used locked : true property and set a static width to those columns. Yet nothing is happening. I have checked all possible docs. Not sure where the mistake lies. Could someone please help me?
Code is as given below
View.js'
Ext.define('MyModel.view.graphPanel', {
extend: 'Ext.grid.Panel',
layout:'border',
alias: 'widget.graphPanel',
name:'graphPanel',
title: 'Tests',
store: 'MyModel.store.settingStore',
viewConfig: {
stripeRows: true
},
columnLines: true,
split:true,
frame: true
});
Controller.js
Ext.define('MyModel.controller.myController', {
extend:'Ext.app.Controller',
models:['MyModel.model.settingModel'],
stores:['MyModel.store.settingStore'],
init: function() {
Ext.Ajax.request({
url: 'Sample.xml',
success: function(response, opts) {
var txt = response.responseText;
parser=new DOMParser();
xmlDoc=parser.parseFromString(txt,"text/xml");
var columnArr = [];
var outercolumnarr = [];
var fieldArr = [];
modelfieldArr = [];
completeDataArr=[];
//This builds all locked set of columns
var headerArr = xmlDoc.getElementsByTagName('HEADER1');
Ext.each(headerArr[0].getElementsByTagName('HEADER2'), function(header, index) {
columnArr.push({
text: header.getAttribute('TEXT'),
dataIndex: header.getAttribute('DATAINDEX'),
locked:true,
width:100,
forceFit: true
});
});
outercolumnarr.push({
text:"General data",
width:400,
columns:columnArr,
locked:true
});
//Building scrollable columns
var days = ['Sun','Mon',Tue'];
Ext.each(days, function(day, index) {
columnArr = [];
Ext.each(headerArr[1].getElementsByTagName('HEADER2'), function(innerHeader, index) {
columnArr.push({
text: innerHeader.getAttribute('TEXT'),
dataIndex: innerHeader.getAttribute('DATAINDEX')
});
});
outercolumnarr.push({
text:day,
columns:columnArr,
});
});
//outercolumnarr contains the final column array
//Similarly build data array, model and field array for stores and models.
var store = Ext.data.StoreManager.lookup('MyModel.store.settingStore');
store.setFields(modelfieldArr);
store.setData(completeDataArr);
//Reconfigure the grid
var gridview = Ext.ComponentQuery.query('graphPanel')[0];
gridview.reconfigure(store,outercolumnarr);
}
});
}
});
Because you are adding columns using reconfigure, enableLocking is not enabled implicitly. You must enable it manually. You may enable it in MyModel.view.graphPanel definition, but probably you'll also need to add empty column definition (columns: []), because I've had error from framework without that.
Working sample: http://jsfiddle.net/nj4nk/11/

highcharts not refreshing chart when page refreshes

i have created a highchart and data i took it from csv file.The chart is working good and plotting fine.But my problem is when the page refreshes it is not taking the latest value from the csv file.It still displays the old chart.when i close the browser and re-open the chart works fine.Please help me how to reset/redraw with updated value from csv
Below is my code. This problem IE not in firefox
var options = {
chart: {
renderTo: 'container',
defaultSeriesType: 'line',
marginRight: 130,
marginBottom: 25
},
title: {
text: 'Support Trending P1,P2 & P3'
},
xAxis: {
categories: []
},
yAxis: {
showLastLabel:true,
tickInterval:5,
title: {
text: ""
}
},
series: []
};
$.get('../data/trending.txt', function(data) {
// Split the lines
var lines = data.split(';');
$.each(lines, function(lineNo, line) {
var items = line.split(',');
// header line containes categories
if (lineNo == 0) {
$.each(items, function(itemNo, item) {
if (itemNo > 0) options.xAxis.categories.push(item);
});
}
// the rest of the lines contain data with their name in the first position
else {
var series = {
data: []
};
$.each(items, function(itemNo, item) {
if (itemNo == 0) {
series.name = item;
} else {
series.data.push(parseFloat(item));
}
});
options.series.push(series);
}
});
var chart = new Highcharts.Chart(options);
});
});
Blockquote
It looks like your chart data is being cached, and not being refreshed by the browser. Without code, it's card to know how to fix it.
If you are using jquery $.ajax, there is an option
cache:false
Which may help. http://api.jquery.com/jQuery.ajax/