I have google chart (line chart), need to customize legend with some extra information. Please refer this http://plnkr.co/edit/ysZwYaAQpMhHarcA2UHq?p=preview [Plunker][1] to know more in detail. I want legend information like this below snap
So if you see in below image, and my fiddle I have R1, R2 , R3 and so on as releases to select, and each release has its own score, so I want that score to be shown as R1 100 just like below image.
Note that graph data is different, and the dropdown for selection of releases data is different. but both have releaseId R1 , R2. So on selection of dropdown value say R1,R2 or R3 I am pushing only that row from graphdata to drawgraph.
So basically, I need to show selected R1 score in legend.
Please give me some idea or link where this is done earlier. Thanks in advance.
to add the score to the legend,
you can add the score to the column label before drawing the chart
replace the drawChart function with the following...
function drawChart() {
var chartColors = [];
var chartColumns = [0];
var checks = document.getElementsByTagName('input');
for (var i = 0; i < $scope.selectedNewRelease.length; i++) {
var seriesColumn = getColumnIndex(x, $scope.selectedNewRelease[i].releaseId);
chartColumns.push(seriesColumn);
x.setColumnLabel(seriesColumn, x.getColumnLabel(seriesColumn) + ' ' + $scope.selectedNewRelease[i].score);
}
var view = new google.visualization.DataView(x);
view.setColumns(chartColumns);
chart.draw(view, options);
if ($scope.selectedNewRelease.length>0) {
$scope.Grtgraph=true;
}else{
$scope.Grtgraph=false;
}
}
function getColumnIndex(data, columnLabel) {
for (var i = 0; i < data.getNumberOfColumns(); i++) {
if (data.getColumnLabel(i) === columnLabel) {
return i;
}
}
}
Related
I have existing charts that displays data for a full day 12:00am - 12:00am.
Now required to change one chart forward to display 4:00am - 4:00am.
I have managed to shift the x axis labels (.add(4, 'hours')) but the chart data is still in the same position.
How do I shift the charted data forward 4 hours?
Limited scope to change global variables as this will impact other charts.
var getChartSeries = function(response, chart_series_data) {
var lines = response.graph_data.lines;
for (var i=0; i<lines.length; i++) {
var series = lines[i];
var dateFormat = graphDateFormat;
if (chartIntraday) dateFormat = 'HH:mm:ss';
var currSeriesData = [];
for (var j=0; j<series.data.length; j++) {
var row = series.data[j];
var yValue = parseFloat(row[1]);
var point = {
x: moment(row[0], dateFormat).add(4, 'hours').valueOf(),
y: yValue,
displayValue: row[3]
};
currSeriesData.push(point);
}
// Set the series name, legend label, and the line identifier
var name = formatLegendLabel(series.display_name, response);
var label = response.label;
if (response.display_name != undefined && response.display_name != '') label = series.display_name + ' : ' + label;
By default chart adjusts extremes to the provided data. To display these few hours before the first point use xAxis.min property.
Live demo: http://jsfiddle.net/kkulig/xqdqooh9/
API reference: https://api.highcharts.com/highcharts/xAxis.min
I have an amChart chart which data is taken from two tables below it (code is modified from this SO answer). Every row the category in each tables begins with different prefix: first table begins with (Sales) and second table begins with (Market).
Here is my code for better illustration: http://jsfiddle.net/uoxbm2d3/2/
Since there are two tables and it's a column/bar chart, I need the columns/bars to be stacked based on from which table or what prefix they have. So (Sales) will only be stacked with (Sales) or, in other words, data from Table 1 will only be stacked with Table 1. Same goes with (Market)/Table 2 that will only be stacked with its siblings. Something like this:
The green/yellow/orange color is from Table 1 (Sales); the blue/purple color is from Table 2 (Market).
Is there any way to tell the function which graph comes from which table? Or at least to tell the function which data has which prefix?
Here is a piece of the script
function generateGraphsFromData(chart, chartData) {
//get the chart graph value fields as lookup table with a seen property set to false by default
//this will be used to determine what graphs need to be removed when looking at the data
var graphValueFields = chart.graphs.reduce(function(valueFields, graph) {
valueFields[graph.valueField] = 0;
return valueFields;
}, {});
var removeValueFields = [];
//create an array of new graph value fields by filtering out the categoryField
//and the currently known valueFields.
var newGraphValueFields = [];
Object.keys(chartData[0]).filter(function(key) {
return key != chart.categoryField;
}).forEach(function(valueField) {
//if this is a new graph, add it to the list
if (graphValueFields[valueField] === undefined) {
newGraphValueFields.push(valueField);
} else {
//otherwise, set the seen flag to 1
graphValueFields[valueField] = 1;
}
});
//for each new value field left over, create a graph object and add to the chart.
newGraphValueFields.forEach(function(valueField) {
var graph = new AmCharts.AmGraph();
graph.title = valueField;
graph.valueField = valueField;
graph.balloonText = "<strong>[[title]]</strong><br /> Rp[[value]]";
graph.id = valueField; //use the valueField as the ID for ease of removal
graph.type = 'column';
graph.lineAlpha = 0;
graph.fillAlphas = 0.5;
graph.bullet = "none";
graph.stackable = true; // disable stacking
chart.addGraph(graph);
});
//loop through the graphValueFields lookup table and remove all graphs that were not seen when
//rescanning the data
Object.keys(graphValueFields).forEach(function(removeGraphValueField) {
if (graphValueFields[removeGraphValueField] === 0) {
chart.removeGraph(chart.getGraphById(removeGraphValueField));
}
})
}
Once you add your new graphs and remove any old ones, you can sort by title then loop through them again to find the first non-matching prefix and set the graph's newStack property to true while setting it to false in the rest of the graphs. For example:
chart.graphs.sort(function(lhs, rhs) {
//sort by title, ensures that the sales (first table) data comes first
var lhsSalesIdx = lhs.title.indexOf('(Sales)');
var rhsSalesIdx = rhs.title.indexOf('(Sales)');
if (lhsSalesIdx !== -1 && rhsSalesIdx === -1) {
return -1;
}
else if (lhsSalesIdx === -1 && rhsSalesIdx !== -1) {
return 1;
}
else {
return lhs.title.localeCompare(rhs.title);
}
});
var stackSet = false;
//find the first instance of the market row graph and set its newStack property to true
//while clearing out the others
for (var i = 0; i < chart.graphs.length; ++i) {
if (!stackSet && chart.graphs[i].title.indexOf('(Sales)') === -1) {
chart.graphs[i].newStack = true;
stackSet = true;
}
else {
chart.graphs[i].newStack = false;
}
}
Updated fiddle - note that I set stackable back to true in your new graph loop for this to work as well.
Below is the code that I use to load colors to the svg map that I have based on the winning party taken from a spreadsheet with an array. The problem that I am currently facing is that there is an error in the loop and it identified only the first nine paths and applied the color and left the rest. Can someone help me identify and fix these issues. I am still learning from my mistakes and help would be appreciated.
<![CDATA[
var resultData = [];
var uniqueparty= [];
var wincolor = [];
$.getJSON("https://spreadsheets.google.com/feeds/list/1IoNqeReOPKNFrYMlK2rnJVuMaLeAgnZneLbKYSQ7bs4/od6/public/values?alt=json", function(data) {
var len = data.feed.entry.length;
for (var i=0; i<len; i++) {
//first row "title" column
var current = data.feed.entry[i];
resultData[i]= [
current.gsx$constituency.$t, //0
current.gsx$winner2010.$t, //1
current.gsx$winningparty.$t, //2
current.gsx$candidatename1.$t, //3
current.gsx$party1.$t,//4
current.gsx$candidatename2.$t,//5
current.gsx$party2.$t,//6
current.gsx$candidatename3.$t,//7
current.gsx$party3.$t//8
];
//Moving Winning party names alone to an array
wincolor[i]=[current.gsx$winningparty.$t];
}
//Remove duplicates from the winning party array to another array
uniqueparty = wincolor.filter(function (el) {
if (this[el]) {
this[el] = 1;
return el;
}
return true;
}, {});
//uniqueparty.sort();
//Specify colors for the party
var colors = ["#FE9A2E", "#F2F5A9", "#81F781", "#F2F5A9", "#58ACFA", "#F3F781", "#F5A9F2", "#81F7F3", "#F5A9A9"];
//assign color using loop based on element ID
for(i=0; i<wincolor.length; i++){
for(j=0; j<uniqueparty.length; j++){
if(uniqueparty[j]==resultData[i][2]){
var paths = document.getElementById(resultData[i][0]);
paths.style.fill=colors[j];
break;
}
}
}
});
]]>
I have included the spreadsheet from which the data is retreived and also the svg map
https://docs.google.com/spreadsheets/d/1IoNqeReOPKNFrYMlK2rnJVuMaLeAgnZneLbKYSQ7bs4/pubhtml?gid=0&single=true
http://jsfiddle.net/diviseed/3ncos0uk/1/
Is it possible to get the lowest value in the chart itself assuming that the data is dynamic?Take a look at this example Fiddle.
$(function () {
var d1 = [];
for (var i = 0; i < 14; i += 0.5)
d1.push([i, Math.sin(i)]);
$.plot($("#placeholder"), [ d1]);
});
How can I get the lowest value in this line chart?
Update: It seems my earlier example didn't quite make sense please take a look at this link: https://abtw.alliancebernstein.com.tw/APAC/TW/Funds/American-Income.htm?ShareClassId=60006908 make sure to turn off Flash plugin so that Flotchart will render. Now looking at the area chart I want to get the lowest value base on the chart rendered. Is this possible?
If you save your plot object like so
var plot = $.plot($("#placeholder"), [ d1]);
you can get the minimum value from it with
var minimum = plot.getData()[0].yaxis.datamin;
The same is possible for maximum value (datamax), for the xaxis and for other data series (the index behind getData()).
http://jsfiddle.net/fenderistic/Sf5Yr/
Simply keep a lowest variable, and check throughout the for-loop to see if the value lower, if so, replace the current lowest value with it.
$(function () {
var d1 = [];
//Assuming you're always starting at zero
var lowest = Math.sin(0);
for (var i = 0; i < 14; i += 0.5) {
d1.push([i, Math.sin(i)]);
if (Math.sin(i) < lowest) {
lowest = Math.sin(i);
}
}
alert(lowest)
$.plot($("#placeholder"), [d1]);
});
I have been working on a scheduling website for the past few weeks. I am showing the schedules as PHP generated html-tables. I use merged cells for showing events. I have come to a problem when trying to delete events using JS. Since those are merged cells, using rowspan, I have to go through the table and re-adding empty cells whenever there is a need when I delete one. My solution is working fine for when my table contains one merged cell among nothing but empty cells, but with a more complex table, it fails. I can't really grasp what's wrong with it, except that it doesn't correctly find the cellIndex anymore. Does anyone have a clue? Here is what I'm talking about:
http://aturpin.mangerinc.com/table.html
(Click on an event to remove it, or attempt to anyhow)
This sample may help you find your solution. It seems to demonstrate your problem as well as have some sample code to generate a matrix to help you solve it.
EDIT: I liked the puzzle and decided to play with it for a bit, here is a "functioning" example of implementing that sample (although sometimes the table doesn't seem to redraw correctly. This should probably help you get further along the way.
function getTableState(t) {
var matrix = [];
var lookup = {};
var trs = t.getElementsByTagName('TR');
var c;
for (var i=0; trs[i]; i++) {
lookup[i] = [];
for (var j=0; c = trs[i].cells[j]; j++) {
var rowIndex = c.parentNode.rowIndex;
var rowSpan = c.rowSpan || 1;
var colSpan = c.colSpan || 1;
var firstAvailCol;
// initalized the matrix in this row if needed.
if(typeof(matrix[rowIndex])=="undefined") { matrix[rowIndex] = []; }
// Find first available column in the first row
for (var k=0; k<matrix[rowIndex].length+1; k++) {
if (typeof(matrix[rowIndex][k])=="undefined") {
firstAvailCol = k;
break;
}
}
lookup[rowIndex][c.cellIndex] = firstAvailCol;
for (var k=rowIndex; k<rowIndex+rowSpan; k++) {
if(typeof(matrix[k])=="undefined") { matrix[k] = []; }
var matrixrow = matrix[k];
for (var l=firstAvailCol; l<firstAvailCol+colSpan; l++) {
matrixrow[l] = {cell: c, rowIndex: rowIndex};
}
}
}
}
// lets build a little object that has some useful funcitons for this table state.
return {
cellMatrix: matrix,
lookupTable: lookup,
// returns the "Real" column number from a passed in cell
getRealColFromElement: function (cell)
{
var row = cell.parentNode.rowIndex;
var col = cell.cellIndex;
return this.lookupTable[row][col];
},
// returns the "point" to insert at for a square in the perceived row/column
getPointForRowAndColumn: function (row,col)
{
var matrixRow = this.cellMatrix[row];
var ret = 0;
// lets look at the matrix again - this time any row that shouldn't be in this row doesn't count.
for (var i=0; i<col; i++)
{
if (matrixRow[i].rowIndex == row) ret++;
}
return ret;
}
};
}
function scheduleClick(e)
{
if (e.target.className != 'event')
return;
//Get useful info before deletion
var numRows = e.target.rowSpan;
var cellIndex = e.target.cellIndex;
var rowIndex = e.target.parentNode.rowIndex;
var table = e.target.parentNode.parentNode;
var tableState = getTableState(table);
var colIndex = tableState.getRealColFromElement(e.target);
//Deletion
e.target.parentNode.deleteCell(cellIndex);
//Insert empty cells in each row
for(var i = 0; i < numRows; i++)
{
var row = table.rows[rowIndex + i];
row.insertCell(tableState.getPointForRowAndColumn(rowIndex+i, colIndex));
}
}