Jquery Highcharts is not loading when using with common function? - javascript

I am working with jquery HighCharts. I want to create a common function to develop multiple charts of same type.
To achieve this goad I created a function as follow -
function generateGraph(data) {
var dates = new Array();
var startDate = "";
for (var i = 0; i < data.length; i++) {
dates[i] = data[i].date;
}
var productInsight = _comm.getProductInsightArray();
var productInsight_Array = new Array();
$.each(productInsight, function(key, value) {
productInsight_Array.push(key);
});
if(dates.length > 0) {
startDate = dates[0].split("/");
}
intervals = 24 *3600 * 1000; //one day
var title = $("#DateSearch_analytics_Similar_Stores1").val();
var color = ['#000000', '#FFFFFF', '#000080', '#0000FF', '#808080'];
var containers =['container1', 'container2','container3','container4', 'container5', 'container6', 'container7', 'container8', 'container9'];
for(var j=0; j<containers.length; j++)
{
var chart = new Highcharts.Chart({
chart: {
zoomType: 'x',
renderTo: containers[j],
type: 'line',
},
title: {
text: title
},
subtitle: {
text: document.ontouchstart === undefined ?
'Click and drag in the plot area to zoom in' :
'Pinch the chart to zoom in'
},
xAxis: {
type: 'datetime',
tickInterval: intervals,
},
series: []
});
for(var i=0; i < productInsight_Array.length; i++) {
var fillData = new Array();
var counter = 0;
var productValue = document.getElementById('product-nm').value;
$.each(dates, function() {
fillData[counter] = _comm.randomNumberFromRange(_randomNumberStartRange, _randomNumberEndRange);
counter++;
});
chart.addSeries({
name: productInsight_Array[i],
type: 'line',
color: color[i],
pointStart: Date.UTC(startDate[2], startDate[0] - 1, startDate[1]),
pointInterval: intervals,
data: fillData,
});
}
$("text:contains('Highcharts.com')").css("display", "none");
}
}
Its working fine and developing charts on window load and button click. I am saving these graph in 9 container but this script is not loading graph in 3rd container and when I remove 3rd container than its not loading in fourth and so on. But it works fine when I call this function on button click in place of document load.
I am little surprised why its happing, As a common function creting all graphs.
I need your help! :(
Thanks

The problem is when load the function your markup doesnt exists. For this reason when you click the button works ok. When the button is visible, all markup is already loaded.
Review your load order.
Also aside comment: put this in your chart declaration:
credits: {
enabled: false
}
To not show the credits message: "Highcharts.com".
An example

Related

Multiple charts with same data not loading in same page: Highcharts

I am trying to display Highchart having same data in custom no. of times, Say I want to display the chart 2 times in same pagedynamically.
What I have done is that I set the chart in for loop in which I can repeat the chart multiple times dynamically.
Here is the Script That I have tried.
var len = 2 ;
var chartArea = document.getElementById("content");
for(var i=0;i<len;i++)
{
console.log("I", i);
chartArea.innerHTML +=
'<div id="container'+i+'"></div>';
var categories = ["1","2","3","4","5","6","7","8","9","10"];
Highcharts.stockChart('container'+i, {
rangeSelector: {
enabled: false
},
xAxis: {
labels: {
formatter: function() {
return categories[this.value];
}
}
},
navigator: {
xAxis: {
labels: {
formatter: function() {
return categories[this.value];
}
}
}
},
plotOptions: {
series: {
animation: {
duration: 2000
},
marker:{
enabled: false
}
}
},
series: [{
data: [3,5,3,6,2,6,4,9,4,6]
}]
});
But the problem is that only last graph shows the line chart. the other first chart have the x-axis labels bu the line graph is not showing.
Here is the Fiddle That I have tried.
http://jsfiddle.net/abnitchauhan/cenmohbw/
You forgot to append the child to the DOM tree.
When you create a new HTML element dynamically, it needs to be attached to an existing node in the DOM tree.
In Javascript you can do:
var existingNode = document.getElementById("content");
var newElement = document.createElement("div");
newElement.id = "someID";
existingNode.appendChild(newElement);
In jQuery, its more easy:
$("#content").append(`<div id="someID"></div>`);
In your case, the change would look like (only for loop changes) as:
for (var i = 0; i < len; i++) {
console.log("I", i);
$("#content").append(`<div id="container${i}"></div>`);
// rest of your code

CanvasJS not properly rendering chart

I am using the following code to render an OHLC chart in CanvasJS:
<script>
var candleData = [];
var chart = new CanvasJS.Chart("chartContainer", {
title: {
text: 'Demo Stacker Candlestick Chart (Realtime)'
},
zoomEnabled: true,
axisY: {
includeZero: false,
title: 'Price',
prefix: '$'
},
axisX: {
interval: 1,
},
data: [{
type: 'ohlc',
dataPoints: candleData
}
]
});
function mapDataToPointObject(data) {
var dataPoints = [];
for(var i = 0; i < data.length; i++) {
var obj = data[i];
var newObj = {
x: new Date(obj.time),
y: [
obj.open,
obj.high,
obj.low,
obj.close
]
}
dataPoints.push(newObj);
}
return dataPoints;
}
function updateChart() {
$.ajax({
url: 'http://localhost:8080',
success: function(data) {
candleData = JSON.parse(data);
candleData = mapDataToPointObject(candleData);
chart.render();
}
});
}
$(function(){
setInterval(() => {
updateChart();
}, 500);
});
The data properly loads, parses into the correct format, and render() is called on the interval like it should. The problem is, while the chart axes and titles all render properly, no data shows up. The chart is empty.
What DOES work is setting the data directly to the chart using
chart.options.data[0].dataPoints = candleData;
Why does my above solution not work then? Is there a way I can update the chart's dataPoints without having to hardcode a direct accessor to the chart's dataPoints?
It's related to JavaScript pass by value and pass by reference.
After execution of the following line.
dataPoints: candleData
dataPoints will refer to the current value of candleData. ie. dataPoints = [];
Now if you redefine candleData to any other value.
candleData = JSON.parse(data);
candleData = mapDataToPointObject(candleData);
Then dataPoints won't be aware of this update and will still refer to the empty array (that you pointed earlier).
The following snippet will make it easy to understand
//pass by value
var a = "string1";
var b = a;
a = "string2";
alert("b is: " + b); //this will alert "string1"
//pass by reference
var c = { s: "string1" };
var d = c;
c.s = "string2";
alert("d.s is: " + d.s); //this will alert "string2"
For more, you can read about pass by value and pass by reference.
Javascript by reference vs. by value
Explaining Value vs. Reference in Javascript

Diagram interval goes slower and slower (Canvas.JS)

The problem I am encountering is that when I click to view the diagram via JQuery event click, the diagram works fast and smoothly, but if I double click or perhaps click 10 times, for each click the diagrams runs slower and slower. That is to say the click is dependend on the diagram performance. I believe the $.getscript() is causing this low performance, or poor JQuery code..
JQuery event below is responsible for displaying the diagram. Keep in mind that the user has the oppertunity to navigate between the diagrams, they can only view one diagram once.
$('[data-row]').on('click', function() {
var row = $(this).attr('data-row');
$('.active').removeClass('active'); // Displaye:none
$('#table' + row).addClass('active'); // Display:block
if(row == 1){
$.getScript("diagram1.js"); // Display diagram1
} else {
}
});
This is diagram1.js.
(function (){
$(document).ready(function(){
var dps = []; // data
var chart = new CanvasJS.Chart("diagram1 ",
{
title:{
text: "Exhaust Temperature"
data: [
{
type: "spline",
name: "Temp Cylinder 1",
showInLegend: "true",
legendText: "Temp Cylinder 1",
dataPoints: dps1
}
});
var xVal = 0;
var updateInterval = 50;
var dataLength = 50;
var updateChart = function (count) {
count = count || 1;
for (var j = 0; j < count; j++) {
dps.push({
x: xVal,
y: EXTS[1]
});
xVal++;
};
if (dps.length > dataLength )
{
dps.shift();
}
chart.render();
};
// generates first set of dataPoints
updateChart(dataLength);
// update chart after specified time.
setInterval(function(){updateChart()}, updateInterval);
});
}());

HighCharts Loading from CSV File with Many Data Points

After much searching and wanting to bang my head against my desk, I'm posting my first question on stackoverflow.
I've got an ASP.NET web application that is generating some data on the server side and creating a CSV file on the server.
I'm using HighCharts to produce a graph. Everything is working great, however, depending on what kind of date range a user runs there can be a few data points or many data points.
The problem comes in when there are many data points. Look at the X-Axis, and you'll see what I mean. Is there anyway to "group" these where it doesn't show every single point on the X-Axis?
The dates are at random intervals.
I've created a JSFiddle with my client side code and the contents of my CSV file in a JavaScript variable.
Here is my code:
function parseDate(dateStr) {
var matches = dateStr.match(/([0-9]{1,2})\/([0-9]{1,2})\/([0-9]{4})/)
return Date.UTC(matches[3], matches[1]-1, matches[2]);
}
var csv = 'Chart,3/4/2007,3/24/2007,4/13/2007,4/25/2007,9/19/2007,9/28/2007,11/5/2007,1/7/2008,1/14/2008,1/21/2008,1/27/2008,2/3/2008,2/10/2008,2/17/2008,2/24/2008,3/2/2008,3/23/2008,3/30/2008,4/5/2008,4/21/2008,5/3/2008,5/10/2008,5/17/2008,5/24/2008,5/31/2008,6/8/2008,6/15/2008,6/29/2008,7/4/2008,7/18/2008,7/25/2008,8/1/2008,8/8/2008,9/17/2010,11/25/2010,8/16/2012,1/17/2013,1/27/2013\nDates,180.00,175.50,167.00,166.50,170.00,171.50,174.00,163.00,162.50,164.00,166.50,166.50,167.50,170.00,170.00,171.00,169.00,166.50,166.00,166.50,162.00,160.00,160.50,162.50,164.00,164.00,165.00,165.50,166.00,169.00,171.00,170.00,171.00,165.00,165.00,189.00,177.00,175.50';
var options = {
chart: {
renderTo: 'chart',
defaultSeriesType: 'line'
},
title: {
text: 'Test Chart'
},
xAxis: {
type: 'datetime',
categories: []
},
yAxis: {
title: {
text: 'Pounds'
}
},
series: []
};
// Split the lines
var lines = csv.split('\n');
$.each(lines, function(lineNo, line) {
var items = line.split(',');
if (lineNo == 0) {
$.each(items, function(itemNo, item) {
if (itemNo > 0) options.xAxis.categories.push(parseDate(item));
});
}
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);
Here is the link to JSFiddle:
http://jsfiddle.net/Q2hyF/6/
Thanks in Advance,
Robert
Check out HighStocks and its DataGrouping feature:
http://www.highcharts.com/stock/demo/data-grouping
It can handle much larger datasets than HighCharts can. However, there are drawbacks as the newest HighCharts features are not always immediately in HighStocks. There are generally only minor changes needed to your syntax to use HighStocks, if you want to test it.
I ended up getting this working and never posted the answer... Here is the answer.
Take a close look at:
series.data.push([parseDate(points[0]), parseFloat(points[1])]);
in the code below...
function parseDate(dateStr) {
var matches = dateStr.match(/([0-9]{1,2})\/([0-9]{1,2})\/([0-9]{4})/)
return Date.UTC(matches[3], matches[1] - 1, matches[2]);
}
var csv = 'Chart,11/1/2013|6,11/2/2013|4,11/3/2013|6,11/4/2013|3,11/5/2013|5,11/6/2013|5,11/7/2013|5,11/8/2013|6,11/9/2013|4,11/10/2013|13,11/11/2013|12,11/12/2013|3,11/13/2013|5,11/14/2013|7,11/15/2013|9,11/16/2013|0,11/17/2013|2,11/18/2013|3,11/19/2013|2,11/20/2013|16,11/21/2013|6,11/22/2013|9,11/23/2013|9,11/24/2013|20,11/25/2013|10,11/26/2013|10,11/27/2013|4,11/28/2013|9,11/29/2013|7,11/30/2013|7';
var options = {
chart: {
renderTo: 'chart',
type: 'line'
},
title: {
text: 'Sales'
},
xAxis: {
type: 'datetime'
},
series: []
};
var lines = csv.split('\n');
$.each(lines, function (lineNo, line) {
var items = line.split(',');
var series = {
data: []
};
$.each(items, function (itemNo, item) {
if (itemNo == 0) {
series.name = item;
} else {
var points = item.split('|');
series.data.push([parseDate(points[0]), parseFloat(points[1])]);
}
});
options.series.push(series);
});
var chart = new Highcharts.Chart(options);
http://jsfiddle.net/rswilley601/gtsLatyr/

Google Column Chart cropping the bars

I am trying to display data using Google's Column chart. I tried displaying bars not stacked but it would not display one bar from both ends. Then i changed the property isStacked to true, it displays all the bars but it crops the bar at the both ends.
How can i fix this issue?
I was playing around with the options but nothing seems to work.
<script type='text/javascript'>
google.load('visualization', '1', { 'packages': ['corechart'] });
google.setOnLoadCallback(drawSizeChart);
var d = 0;
function drawSizeChart() {
$.post('/metrics/SiteResourceChart', { fnsId: "#Model.FnsId", regionId: selectedValue },
function (data) {
if (Object.keys(data).length !== 0) {
var tdata = new google.visualization.DataTable();
tdata.addColumn('date', 'Date');
for (var p = 0; p < data.length; ++p) {
tdata.addColumn('number', data[p][0].PathName);
}
d = data[0].length;
for (var i = 0; i < data.length; ++i) {
for (var j = 0; j < data[i].length; ++j) {
var date = new Date(parseInt(data[i][j].CreatedAt.substr(6)));
var rCount = data[i][j].ResourceCount;
if (i === 0)
tdata.addRow([date, rCount, null]);
else
tdata.addRow([date, null, rCount]);
}
}
var options = {
title: 'Resource Count',
titleTextStyle: { fontSize: 20 },
isStacked: true,
bar: { groupWidth: '20%' },
chartArea: { left: '50' },
hAxis: { viewWindowMode: 'maximized' }
//legend: { position: 'none' }
};
var chart = new google.visualization.ColumnChart(document.getElementById('site_size_chart'));
chart.draw(tdata, options);
}
}
);
}
</script>
I guess a quick solution would be to define your first column as 'string' instead of Date and leave the hAxis.viewWindowMode as default. Otherwise, you should configure hAxis.viewWindow object (i.e., min/max values).
Same issue here. What I did is that I added dummy data with a 0 value one day before the first date and one day after the last date in order to achieve the desired result.
Using the columnchart package wasn't a solution for me because I had days without data but wanted to keep the time axis proportional.

Categories