Google charts: identify a specific control - javascript

Is there a way to identify which control in a set of bound controls is changed by the user?
In this instance I want to know that in a set of 5 bound controls, the user just changed control 3.
I want to resize the div that the control is within, based on the number of distinct values the user has chosen. I can get these, but I cannot identify which control has been changed.
So, something like:
var controlPicker1 = new google.visualization.ControlWrapper({
"controlType": "CategoryFilter",
"containerId": "control1",
"options": {
"filterColumnLabel": "Media source",
"ui": {
"labelStacking": "horizontal",
"allowTyping": true,
"allowMultiple": true
}
}
});
var view = new google.visualization.DataView(data);
barChart = new google.visualization.ChartWrapper({
"chartType": "BarChart",
"containerId": "chart_div",
"options": {
"width": "100%",
"height": "120%",
"vAxis": {title: "Media source (Branch - Dialled number)"},
"hAxis": {title: "Number of calls"},
"fontSize": 14,
"chartArea": {top: 0, right: 0, bottom: 0, height:"100%", width:"70%"}
},
"view": {"columns": [0,6,7,8,9,10,11]}
});
google.visualization.events.addListener(dashboard, "ready", function() {
barChart.draw();
resizeControl("control1", 50, barChart.getDataTable().getDistinctValues(1), 500);
}
});
dashboard.bind(controlPicker1, controlPicker2);
dashboard.bind(controlPicker2, controlPicker3);
dashboard.bind(controlPicker3, controlPicker4);
dashboard.bind(controlPicker4, controlPicker5);
dashboard.bind(controlPicker5, barChart);
dashboard.draw(view);
}
function resizeControl(name, total, div1, length) {
var control=div1.length;
if(total>control){
var div=document.getElementById(name);
var w=parseInt(div.style.width);
var revs=($(this).width()/length);
var newh = 35;
for (var i=0; i <(control / revs); i++) {
if(i>0)newh = newh+25;
}
newh + "px";
$(div).height(newh);
}
}
Thanks,
H.

There's not a lot of information in your post. So I'll show you how to responder to a sort event in a Table.
google.visualization.events.addListener(table, 'sort',
function(event) {
data.sort([{column: event.column, desc: !event.ascending}]);
chart.draw(view);
});
So depending on your chart type:
google.visualization.events.addListener(map, 'select',
function() {
table.setSelection(map.getSelection());
});
Find the event you want, add the listener to the chart.

Related

Amcharts make Guide line value dynamic with SSE

im trying to add a line to amcharts like this image :
its avaliable in amcharts but only on hover ,i want to add it so it will be always there without hover , i tried to Use Am charts Guides as following :
"guides": [{
"valueField":"high",
"value": this part need to be dynamic,
"lineAlpha": 1,
"lineThickness": 1,
"lineColor": "#fff",
"label": 'high'
}],
this way the line is working but it needs a value to be drawn ,the value i want it to be dynamic and changes with SERVER SENT EVENTS ,
You can add the guide after you get your server event and/or change it depending on how your app is structured. Any additions or changes to the chart properties or data require that you call the chart instance's validateData() method.
For adding a new guide (assuming regular serial chart with the guides inserted at the top level of the config):
chartInstance.guides.push({
"value": /*your value here*/,
"lineAlpha": 1,
"lineThickness": 1,
"lineColor": "#fff",
"label": 'high'
});
chartInstance.validateData();
For updating a guide (assuming you're updating the first guide in the array):
//assuming you're updating the first guide in the array:
chartInstance.guides[0].value = /*new value*/
chartInstance.validateData();
Note that guides don't have a valueField. You can see a full list of properties here.
Here's a demo that adds a guide and then randomly changes the guide position every three seconds to demonstrate:
function generateChartData() {
var firstDate = new Date();
var chartData = [];
firstDate.setHours(0, 0, 0, 0);
firstDate.setDate(firstDate.getDate() - 30);
for (var i = 0; i < 30; i++) {
var newDate = new Date(firstDate);
newDate.setDate(newDate.getDate() + i);
var open = Math.round(Math.random() * 30 + 100);
var close = open + Math.round(Math.random() * 15 - Math.random() * 10);
var low;
if (open < close) {
low = open - Math.round(Math.random() * 5);
} else {
low = close - Math.round(Math.random() * 5);
}
var high;
if (open < close) {
high = close + Math.round(Math.random() * 5);
} else {
high = open + Math.round(Math.random() * 5);
}
var value = Math.round(Math.random() * 30 + 100);
chartData[i] = {
date: newDate,
open: open,
close: close,
high: high,
low: low,
value: value
};
}
return chartData;
}
var chart = AmCharts.makeChart("chartdiv", {
type: "serial",
theme: "black",
dataProvider: generateChartData(),
valueAxes: [
{
position: "right"
}
],
graphs: [
{
type: "candlestick",
valueField: "value",
openField: "open",
highField: "high",
lowField: "low",
closeField: "close",
lineColor: "#7f8da9",
fillColors: "#7f8da9",
negativeLineColor: "#db4c3c",
negativeFillColors: "#db4c3c",
fillAlphas: 1
}
],
categoryField: "date",
categoryAxis: {
parseDates: true,
equalSpacing: true
}
});
//simulating events using a 3 second interval
setInterval(function() {
if (chart.guides.length) {
chart.guides[0].value = Math.floor(Math.random() * 30 + 100);
} else {
chart.guides.push({
value: Math.floor(Math.random() * 30 + 100),
lineAlpha: 1,
lineThickness: 1,
lineColor: "#fff",
inside: true,
label: "high"
});
}
chart.validateData();
}, 3000);
#chartdiv {
width: 100%;
height: 300px;
background: #0d0d0d;
}
<script src="//www.amcharts.com/lib/3/amcharts.js"></script>
<script src="//www.amcharts.com/lib/3/serial.js"></script>
<script src="//www.amcharts.com/lib/3/themes/black.js"></script>
<div id="chartdiv"></div>

AMChars, Zoom to certain countries with external buttons

OK, so I have this map in AMCharts where I have external buttons that contain IDs, LAT and Long of certain countries, and when I hover over them I want the map to zoom and center itself to that country, here's the code example ...
http://codepen.io/sheko_elanteko/pen/rjYvgE
var map = AmCharts.makeChart("chartdiv", {
"type": "map",
"dataProvider": {
"map": "worldLow",
"getAreasFromMap": true,
"areas": [ {
"id": "EG",
"color": "#67b7dc",
"rollOverOutlineColor": "#000",
"autoZoom": true,
"balloonText": "Egypt"
}, {
"id": "KZ",
"color": "#67b7dc",
"rollOverOutlineColor": "#000",
"autoZoom": true,
"balloonText": "Kazakistan"
}, {
"id": "US",
"color": "#67b7dc",
"rollOverOutlineColor": "#000",
"autoZoom": true,
"balloonText": "United States"
}]
},
"areasSettings": {
"color": "#999",
"autoZoom": false,
// "selectedColor": "#CC0000",
"balloonText": "",
"outlineColor": "#fff",
"rollOverOutlineColor": "#fff"
},
"listeners": [{
"event": "rendered",
"method": function(e) {
// Let's log initial zoom settings (for home button)
var map = e.chart;
map.initialZoomLevel = map.zoomLevel();
map.initialZoomLatitude = map.zoomLatitude();
map.initialZoomLongitude = map.zoomLongitude();
}
}]
});
function centerMap() {
map.zoomToLongLat(map.initialZoomLevel, map.initialZoomLongitude, map.initialZoomLatitude);
}
$("button.country").mouseenter(function(event) {
event.stopPropagation();
var countryID = $(this).data("id");
var country = map.getObjectById(countryID);
var lat = $(this).data("lat");
var long = $(this).data("long");
country.color = '#000';
// map.zoomToSelectedObject(country);
map.zoomToLongLat(3, lat, long);
country.validate();
}).mouseleave(function(event){
event.stopPropagation();
var countryID = $(this).data("id");
var country = map.getObjectById(countryID);
country.color = '#CC0000';
country.validate();
centerMap();
});
As you can see I have the coordinates of each country hard coded, as well as the zoom level, but the zooming doesn't work properly, especially for US!!
I also wonder if there's a way to get the LAT and Long of each country so that I don't hard-code them.
There's a function in AMCharts called "zoomToSelectedObject", but I tried that and gave it the object with no luck.
You could try amCharts' selectObject method. Its default function is to zoom to the map object provided (the one that you already get by using getObjectById. Example:
$("button.country").mouseenter(function(event) {
event.stopPropagation();
var countryID = $(this).data("id");
var country = map.getObjectById(countryID);
map.selectObject(country);
}).mouseleave( ... );
Just make sure that you add "selectable": true to your areasSettings. Without it, the selectObject method won't work.
amCharts maps have excellent docs that you'll find here: https://docs.amcharts.com/3/javascriptmaps/AmMap#selectObject.

Kendo UI chart: adjust label amount dynamically

I have a zoomable area chart and an x-axis label for every datapoint. When the chart loads, there is way too many labels, therefor I set the step option:
categoryAxis: {
name: 'CatAxis',
categories: graphLabels,
step: 30
}
But when the user zooms in, I need to decrease the amount of steps, otherwise no labels will be shown at all.
Therefor I subscribed to the zoomEnd event and calculate the desired amount of step:
function onZoomEnd(e) {
var xRange = e.axisRanges.CatAxis;
if (xRange) {
var diff = xRange.max - xRange.min;
var step = 1;
while (diff / step > 6) {
step++;
}
e.sender.setOptions({ categoryAxis: { labels: { step: step } } });
}
But setting the options here causes the chart to refresh and thereby losing its zoom level. The ultimate goal is to show a reasonable amount of labels without them overlapping or disappearing when zooming in and out. Any ideas how to achieve this?
you can maintain the zoom level of the chart using the following example from documentation
https://docs.telerik.com/kendo-ui/knowledge-base/maintain-pan-zoom-state
<button id="rebind">Rebind Chart</button>
<div id="chart"></div>
<script>
// Sample data
var data = [];
for (var i = 0; i < 100; i++) {
var val = Math.round(Math.random() * 10);
data.push({
category: "C" + i,
value: val
});
}
function createChart() {
var axisMin = 0;
var axisMax = 10;
function updateRange(e) {
var axis = e.sender.getAxis('axis')
var range = axis.range()
axisMin = range.min;
axisMax = range.max;
}
function restoreRange(e) {
e.sender.options.categoryAxis.min = axisMin;
e.sender.options.categoryAxis.max = axisMax;
}
$("#chart").kendoChart({
renderAs: "canvas",
dataSource: {
data: data
},
categoryAxis: {
name: "axis",
min: axisMin,
max: axisMax,
labels: {
rotation: "auto"
}
},
series: [{
type: "column",
field: "value",
categoryField: "category"
}],
pannable: {
lock: "y"
},
zoomable: {
mousewheel: {
lock: "y"
},
selection: {
lock: "y"
}
},
zoom: updateRange,
drag: updateRange,
dataBound: restoreRange
});
}
$("#rebind").click(function() {
$("#chart").data("kendoChart").dataSource.read();
});
$(document).ready(createChart);
</script>

Google Annotationchart - Rebase index=100 upon Rangechange

I have an Google Annotation Chart to show relative performance of different investments. User should be able compare performance over a selected time frame, that is, the series values should be rebased / indexed to 100 at the startdate of the visible range of the chart once the timeframe is changed.
Other packages like Amcharts offer a "comparable" function, so have been looking for options like "scaleColumns" and "scaleType" in Google Docs and in other questions here, not finding any clue on how to do this.
Is there any feature I can use and might have missed, or what would be the best approach to recalculate the DataTable with index=100 upon "rangechange".
Code and screenshot is below:
google.charts.load('current', {
packages: ['corechart', 'line', 'table','annotationchart']
});
google.charts.setOnLoadCallback(drawChart);
// ---------- Chart ---------------------------- //
function drawChart() {
//data query
var query = new google.visualization.Query(
'https://docs.google.com/spreadsheets/d/1Gw67zHpKyEd1nu_V698yqYqNgE0x21_ZE_QDHJmsgtE/gviz/tq?gid=803335131&headers=1&range=A1:n451');
query.send(handleQueryResponse);
}
function handleQueryResponse(response) {
if (response.isError()) {
alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage());
return;
}
var data = response.getDataTable();
var options = {
title: 'Development of the choosen Portfolio since 2008',
legend: {
textStyle : { fontSize: 8 },
maxLines : 2,
position: 'top'
},
width: '30%',
height: 700,
lineWidth: 1,
hAxis: {
format: 'M/d/yy',
title: 'Time'
},
vAxis: {
scaleType: 'log',
title: 'Return (log scale)'
},
//theme: 'maximized',
chartArea:{
left:0,
top:20,
width:'30%',
height:'85%'
},
series: {
22: {
lineWidth: 3,
color: 'red'
}
}
};
var chart = new google.visualization.AnnotationChart(document.getElementById('chart_div'))
chart.draw(data, options);
}
google.visualization.events.addListener(chart, 'rangechange', rangechange_handler);
function rangechange_handler(e) {
console.log('You changed the range to ', e['start'], ' and ', e['end']);
// How to recalculate datatable to keep index=100 for all series upon rangechange?
}
Update:
There is a way, working on it: https://groups.google.com/forum/#!searchin/google-visualization-api/compare$20zoom|sort:relevance/google-visualization-api/8HjybllsufY/z5uak6AymLcJ
After an extended period of pain got it working, hope it helps somebody: https://jsfiddle.net/AlexHorn/a9z15syr/
var viewColumns = [0];
var colors = [];
for (var i = 0; i < columnIndices.length; i++) {
viewColumns.push({
label: data.getColumnLabel(columnIndices[i]),
type: 'number',
calc: (function(x) {
// use a closure here to lock the value of i to each column
return function(dt, row) {
// return the value normalized to the first row in the view
return dt.getValue(row, columnIndices[x]) / dt.getValue(0, columnIndices[x]);
};
})(i)
});
}

Highcharts - column chart redraw animation

I'm trying to update an existing data series with a new data array and invoke the redraw function when done. While this works perfectly, I'm not quite satisfied as I'd like to have a sort of grow/shrink transition. I have seen an example by Highcharts (fiddle around with the existing data set then click on the button "Set new data to selected series") but I can't replicate this behavior.
This is what code that I've written:
var series, newSeriesThreshold = this.chart.series.length * 2;
for (var i = 0; i < data.length; i += 2) {
series = {
name: this.data[i].title,
data: this.data[i].data,
color: this.data[i].color
};
if (i >= newSeriesThreshold) {
this.chart.addSeries(series, false);
} else {
var currentSeries = this.chart.series[i / 2];
currentSeries.setData(series.data, false);
}
}
this.chart.redraw();
These are the options when creating the chart:
var config = {
chart: {
renderTo: $(this.container).attr('id'),
type: this.settings.type,
animation: {
duration: 500,
easing: 'swing'
}
},
title: {
text: null
},
legend: {
enabled: this.settings.legend.show
},
tooltip: {
formatter: function() {
return this.x.toFixed(0) + ": <b>" + this.y.toString().toCurrency(0) + '</b>';
}
},
xAxis: {
title: {
text: this.settings.xaxis.title,
style: {
color: '#666'
}
}
},
yAxis: {
title: {
text: this.settings.yaxis.title,
style: {
color: '#666'
}
}
},
series: series,
plotOptions: {
column: {
color: '#FF7400'
}
},
credits: {
enabled: false
}
};
This yields an immediate update without transitioning effects. Any ideas what I might be doing wrong?
I have solved this problem by destroying and creating again the chart.
Here is the link on highcharts forum that helps me : http://forum.highcharts.com/highcharts-usage/animation-on-redraw-t8636/#p93199
The answer comes from the highcharts support team.
$(document).ready(function() {
var chartOptions = {
// Your chart options
series: [
{name: 'Serie 1' , color: '#303AFF', data: [1,1,1,1,1,1,1}
]
};
var chart = new Highcharts.Chart(chartOptions);
$("#my_button").click(function(){
chart.destroy();
chartOptions.series[0].data = [10,5,2,10,5,2,10];
chart = new Highcharts.Chart(chartOptions);
});
});
This remain a mystery. I managed to make the axis update which suggests that there is some kind of animation going on, but it's applied only to the axis, and not the columns.
In the end, I've settled with this behavior.
This might help:
var mychart = $("#mychart").highcharts();
var height = mychart.renderTo.clientHeight;
var width = mychart.renderTo.clientWidth;
mychart.setSize(width, height);
to update all charts
$(Highcharts.charts).each(function(i,chart){
var height = chart.renderTo.clientHeight;
var width = chart.renderTo.clientWidth;
chart.setSize(width, height);
});

Categories

Resources