Google Timeline memory-leak when redrawing chart - javascript

Here is the chart https://jsfiddle.net/damiantt/t2skaegg/2/
<script type="text/javascript" src="//www.google.com/jsapi"></script>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<input id="Draw" type="button" value="Draw" onclick="drawChart();" />
<div id="chart_div_container" style="overflow-x: auto;min-height:0%;">
<div id="chart_div" style="overflow: visible;min-height:0%;"></div>
</div>
<script type="text/javascript">
google.charts.load('current', {
'packages': ['timeline', 'table']
});
var initWidth = $('#chart_div').innerWidth();
var colorMap;
function drawChart() {
$('#chart_div').off();
$('#chart_div').empty();
var data = google.visualization.arrayToDataTable([
['Maszyna', 'Kolor', {
type: 'string',
role: 'tooltip',
'p': {
'html': true
}
}, 'Start Time', 'End Time'],
['one', 'pi1', 'brr',
new Date(2014, 10, 15, 12, 30, 0),
new Date(2014, 10, 15, 12, 30, 20)
],
['one', 'pu3', 'brr',
new Date(2014, 10, 15, 12, 30, 20),
new Date(2014, 10, 15, 12, 30, 45)
],
['one', 'pu3', 'brr',
new Date(2014, 10, 15, 12, 30, 45),
new Date(2014, 10, 15, 12, 30, 55)
],
['two', 'g2', 'brr1',
new Date(2014, 10, 15, 12, 30, 35),
new Date(2014, 10, 15, 12, 30, 55)
],
['two', 'pi1', 'brr2',
new Date(2014, 10, 15, 12, 30, 55),
new Date(2014, 10, 15, 14, 31, 55)
],
['three', 'pu3', 'brr',
new Date(2014, 10, 15, 12, 29, 30),
new Date(2014, 10, 15, 14, 30, 0)
],
['three', 'pi1', 'brr',
new Date(2014, 10, 15, 14, 30, 0),
new Date(2014, 10, 15, 14, 35, 0)
],
['three', 'g2', 'Zbrr',
new Date(2014, 10, 15, 14, 35, 0),
new Date(2014, 10, 15, 15, 25, 10)
],
['three', 'pu3', 'KR1',
new Date(2014, 10, 15, 15, 25, 10),
new Date(2014, 10, 15, 15, 26, 00)
],
['three', 'g2', 'KR2',
new Date(2014, 10, 15, 15, 26, 00),
new Date(2014, 10, 15, 15, 26, 45)
],
['three', 'pi1', 'KR3',
new Date(2014, 10, 15, 15, 26, 45),
new Date(2014, 10, 15, 15, 27, 15)
],
['three', 'pu3', 'brr',
new Date(2014, 10, 15, 15, 27, 15),
new Date(2014, 10, 15, 20, 30, 1)
],
['three', 'pi1', 'brr',
new Date(2014, 10, 15, 20, 30, 1),
new Date(2014, 10, 16, 10, 30, 10)
],
['three', 'pu3', 'brr',
new Date(2014, 10, 16, 10, 30, 10),
new Date(2014, 10, 16, 18, 30, 10)
],
]);
var colors = [];
colorMap = {
// should contain a map of category -> color for every category
pi1: '#e63b6f',
g2: '#19c362',
pu3: '#592df7',
c4: '#000000',
'000000': '#000000'
}
for (var i = 0; i < data.getNumberOfRows(); i++) {
colors.push(colorMap[data.getValue(i, 1)]);
}
var options = {
enableInteractivity: false,
height: 210,
width: initWidth,
colors: colors,
avoidOverlappingGridLines: false,
timeline: {
showBarLabels: false
},
hAxis: {
format: 'dd/MM\nHH:mm'
},
tooltip: {
isHtml: true
}
};
var chart = new google.visualization.Timeline(document.getElementById('chart_div'));
chart.draw(data, options);
afterDraw(data, colors);
$(document).ready(function() {
var zoom = 1000;
var leftSpace = $('rect:first-child+path').position().left - $('#chart_div svg').position().left;
var svgOffset = $('#chart_div svg').offset().left;
var $chartDivCont = $('#chart_div_container');
var x, left, down;
$('#chart_div').on({
'mousemove': function(evt) {
if (down) {
var newX = evt.pageX;
$chartDivCont.scrollLeft(left - newX + x);
}
},
'mousedown': function(evt) {
$('html').css('cursor', 'col-resize');
evt.preventDefault();
down = true;
x = evt.pageX;
left = $chartDivCont.scrollLeft();
},
'mouseup': function() {
down = false;
$('html').css('cursor', 'auto');
},
'mousewheel DOMMouseScroll': function(evt) {
evt.preventDefault();
if (evt.originalEvent.wheelDelta > 0 || evt.originalEvent.detail < 0) {
if (options.width < 31000) {
options.width += zoom;
var prevScrollLeft = $chartDivCont.scrollLeft();
var prop = ($chartDivCont.scrollLeft() + evt.originalEvent.clientX - leftSpace - svgOffset) / ($('#chart_div svg').width() - leftSpace);
chart.draw(data, options);
afterDraw(data, colors);
$chartDivCont.scrollLeft(prevScrollLeft + (prop * 1000));
}
} else {
if (options.width >= initWidth + zoom) {
options.width -= zoom;
var prevScrollLeft = $chartDivCont.scrollLeft();
var prop = ($chartDivCont.scrollLeft() + evt.originalEvent.clientX - leftSpace - svgOffset) / ($('#chart_div svg').width() - leftSpace);
chart.draw(data, options);
afterDraw(data, colors);
$chartDivCont.scrollLeft(prevScrollLeft - (prop * 1000));
}
}
}
});
});
}
function afterDraw(data, colors) {
$rects = $('#chart_div svg > g:nth-child(5) > rect');
for (var i = 0; i < $rects.length; i++) {
$('#chart_div svg > g:nth-child(5) > rect:nth-child(' + (i + 1) + ')').css({
"fill": colors[i]
});
}
}
When i run it on Chrome, memory usage is ~75k. After Draw and max zoom in (zoom it by mouse scroll) memory meter shows 140k, then max zoom out - 180k memory usage, zoom in - 225k, zoom out - 265k.
Is any way to free memory after every draw()? I tried to delete HTML elements, to null variables, but nothing helps me

Related

How to empty() on click with jquery

I need to empty an h2 element when a button is clicked. I do this in part of my code already and it works fine, but when I try to empty this part of my code it doesn't work. I can't figure out why.
JSFiddle link here
$('#help').click(function() {
$('#intro').empty();
$('#intro').text("News:");
$('#help').hide();
$('#noHelp').hide();
$('#news').text("Battle system created");
});
This part is breaking it and I don't know why
var fly = new Monster("fly", 1, 1, 5, 2, 1, 1);
var mouse = new Monster("mouse", 2, 3, 10, 2, 1, 2);
var rat = new Monster("rat", 4, 5, 20, 4, 2, 2);
var rabidChihuahua = new Monster("chihuahua", 6, 8, 35, 6, 1, 4);
var bulldog = new Monster("bulldog", 10, 14, 60, 10, 4, 1);
var wolf = new Monster("Wolf", 15, 18, 65, 12, 3, 6);
var vampie = new Monster("Vampire", 20, 23, 100, 12, 5, 4);
var werewolf = new Monster("Werewolf", 25, 29, 100, 14, 3, 9);
var giantSlime = new Monster("Giant Slime", 31, 38, 200, 7, 15, 1);
var babyDragon = new Monster("Baby Dragon", 39, 50, 150, 16, 9, 5);
var orc = new Monster("Orc", 50, 64, 220, 10, 12, 4);
var succubi = new Monster("Succubi", 61, 80, 190, 21, 8, 12);
var elderDragon = new Monster("Elder Dragon", 75, 100, 300, 21, 15, 8);
var sanaan = new Monster("Sanaan", 150, 500, 500, 55, 45, 30);
I've updated your fiddle :
see here
I've changed this line to test the opt var :
if(opt.length > 0){
monsterList.appendChild(opt); // appending option to select element
}

How to hide bar labels from Google Chart Timeline

I'm trying to remove labels(c1,c2,c3,c4) from my bars.
I tried styling with:
timeline: {barLabelStyle: ...}
but nothing works for me (I thought about set font color to color of bar, but docs says ,,You can't set the color of barLabel text."
jsfiddle: https://jsfiddle.net/550wb2t0/1/
You can use --> timeline: { showBarLabels: false }
google.charts.load('44', {
callback: drawChart,
packages: ['timeline']
});
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Activity', 'Category', 'Start Time', 'End Time'],
['Sleep', 'c1',
new Date(2014, 10, 15, 12, 30, 0, 120),
new Date(2014, 10, 15, 14, 30, 20, 550)
],
['Eat Breakfast', 'c2',
new Date(2014, 10, 15, 12, 30, 55),
new Date(2014, 10, 15, 14, 31, 55)
],
['Commute Home', 'c3',
new Date(2014, 10, 15, 12, 29, 30),
new Date(2014, 10, 15, 14, 30, 0)
],
['Commute Home', 'c4',
new Date(2014, 10, 15, 14, 30),
new Date(2014, 10, 15, 18)
]
]);
var colors = [];
var colorMap = {
// should contain a map of category -> color for every category
c1: '#e63b6f',
c2: '#19c362',
c3: '#592df7',
c4: '#000000'
}
for (var i = 0; i < data.getNumberOfRows(); i++) {
colors.push(colorMap[data.getValue(i, 1)]);
}
console.log(JSON.stringify(colors));
var options = {
height: 450,
colors: colors,
timeline: { showBarLabels: false }
};
var chart = new google.visualization.Timeline(document.getElementById('chart_div'));
chart.draw(data, options);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>

Problems loading the third google chart

I am trying to load three different google charts on page, one gauge, one line and one bar chart. But something fails when i try to implement the third chart. Sometimes the gauge chart and the line chart loads but not the bar chart, other times only the gauge and the bar chart loads. I cant get all three to load at the same time. Can i please get some help?
Here is my code:
<html>
<head>
<title>Usage statistic</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"></script>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("visualization", "1", {
packages: ["corechart", "gauge", "line", "bar"],
'language': 'no'
});
google.setOnLoadCallback(init);
function init() {
drawLine();
drawBar();
drawGauge();
}
function drawGauge() {
var data = google.visualization.arrayToDataTable([
['Label', 'Value'],
['Month', 73.6],
['Today', 62.7],
['Week', 73.6],
]);
var options = {
width: 800,
height: 240,
greenFrom: 40,
greenTo: 100,
redFrom: 0,
redTo: 20,
yellowFrom: 20,
yellowTo: 40,
minorTicks: 5
};
var chart = new google.visualization.Gauge(document.getElementById('gauge_div'));
chart.draw(data, options);
}
function drawLine() {
var data = new google.visualization.DataTable();
data.addColumn('date', 'Date');
data.addColumn('number', 'Logins');
data.addRows([
[new Date(2015, 10, 16), 1971],
[new Date(2015, 10, 17), 1973],
[new Date(2015, 10, 18), 1964],
[new Date(2015, 10, 19), 1981],
[new Date(2015, 10, 20), 1919],
[new Date(2015, 10, 21), 1185],
[new Date(2015, 10, 22), 1104],
[new Date(2015, 10, 23), 2009],
[new Date(2015, 10, 24), 1955],
[new Date(2015, 10, 25), 1933],
[new Date(2015, 10, 26), 1923],
[new Date(2015, 10, 27), 1854],
[new Date(2015, 10, 28), 1159],
[new Date(2015, 10, 29), 1107],
[new Date(2015, 10, 30), 2006],
[new Date(2015, 11, 01), 1998],
[new Date(2015, 11, 02), 1951],
[new Date(2015, 11, 03), 1921],
[new Date(2015, 11, 04), 1870],
[new Date(2015, 11, 05), 1174],
[new Date(2015, 11, 06), 1128],
[new Date(2015, 11, 07), 2030],
[new Date(2015, 11, 08), 1912],
[new Date(2015, 11, 09), 1956],
[new Date(2015, 11, 10), 1942],
[new Date(2015, 11, 11), 1895],
[new Date(2015, 11, 12), 1168],
[new Date(2015, 11, 13), 1148],
[new Date(2015, 11, 14), 2004],
[new Date(2015, 11, 15), 1954],
]);
var options = {
title: 'Logins',
width: 800,
height: 400,
hAxis: {
format: 'MMM d, y',
gridlines: {
count: 15
}
},
vAxis: {
gridlines: {
color: 'none'
},
minValue: 0
}
};
var chart = new google.charts.Line(document.getElementById('line_div'));
chart.draw(data, options);
}
function drawBar() {
var data = new google.visualization.DataTable();
data.addColumn('timeofday', 'Time of Day');
data.addColumn('number', 'Emails Received');
data.addRows([
[
[8, 30, 45], 5
],
[
[9, 0, 0], 10
],
[
[10, 0, 0, 0], 12
],
[
[10, 45, 0, 0], 13
],
[
[11, 0, 0, 0], 15
],
[
[12, 15, 45, 0], 20
],
[
[13, 0, 0, 0], 22
],
[
[14, 30, 0, 0], 25
],
[
[15, 12, 0, 0], 30
],
[
[16, 45, 0], 32
],
[
[16, 59, 0], 42
]
]);
var options = google.charts.Bar.convertOptions({
title: 'Total Emails Received Throughout the Day',
width: 800,
height: 400
});
var chart = new google.charts.Bar(document.getElementById('bar_div'));
chart.draw(data, options);
}
</script>
<style>
.menu {
border-radius: 5px;
border: 1px solid black;
float: left;
padding: 0px 6px;
margin-right: 6px;
color: #686868;
}
.menu a {
text-decoration: none;
color: #686868;
}
.active a {
color: black !important;
}
</style>
</head>
<body style="background-color: #F0F0F0; margin: 20px;">
<div>
<h2>Logins in percentages</h2>
</div>
<div id="gauge_div"></div>
<div>
<h2>Logins last 30 days</h2>
</div>
<div id="line_div"></div>
<div>
<h2>Emails Received</h2>
</div>
<div id="bar_div"></div>
</body>
</html>
I can't really answer why, but if you look at the documentation for loading libraries link, you see that they have updated how it's done. And it's quite differente from before.
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("visualization", "1", {
packages: ["corechart", "gauge", "line", "bar"],
'language': 'no'
});
google.setOnLoadCallback(init);
would have to be changed to
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load("current", {packages: ["corechart", "gauge", "line", "bar"]});
google.charts.setOnLoadCallback(init);
....
</script>
It looks like everything is still working in my applications, with the old loading style, but trying your scenario didn't work at all with the old style. Changeing it to the new one works.
Jsfiddle
EDIT:
If anyone is interested I found out why my things are working. I'm working exclusively with Wrappers, and apparantly you should use google.load (the old way) and not the new google.charts.load.
Source

Multiple trendlines in Google Charts

I need to add multiple trendlines to my google line chart but I just can't figure out how to do it with more than one line.
Here is my code example with a single line based on a date and value to build the chart:
<html>
<head>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
function drawMultipleTrendlineChart() {
var chart;
var data = new google.visualization.DataTable();
data.addColumn('date', 'Date');
data.addColumn('number', 'Sales value');
data.addRow([new Date(2013, 3, 11), 10]);
data.addRow([new Date(2013, 4, 02), 650]);
data.addRow([new Date(2013, 5, 03), 55]);
data.addRow([new Date(2013, 6, 04), 95]);
data.addRow([new Date(2013, 7, 05), 400]);
data.addRow([new Date(2013, 8, 06), 600]);
data.addRow([new Date(2014, 0, 07), 800]);
data.addRow([new Date(2014, 1, 08), 900]);
data.addRow([new Date(2014, 2, 09), 3127]);
var formatter = new google.visualization.NumberFormat({
fractionDigits: 2,
prefix: 'R$:'
});
formatter.format(data, 1);
var dateFormatter = new google.visualization.NumberFormat({
pattern: 'MMM yyyy'
});
dateFormatter.format(data, 0);
var chartHeight = 400;
var chartWidth = 600;
var chartOptions = {
tooltip:{isHtml: true},
trendlines: {
0: {color: 'red'}
},
title: 'Trendlines with multiple lines',
isStacked: true,
width: chartWidth,
height: chartHeight,
colors: ['#0000D8'],
hAxis: {
title: 'example title',
slantedText: false,
slantedTextAngle: 45,
textStyle: {
fontSize: 10
},
format: 'dd-MM-yyyy'
},
chartArea: {
left: 100,
top: 20,
width: (chartWidth - 10),
height: (chartHeight - 90)
}
};
chart = new google.visualization.LineChart(document.getElementById('multipleTrendChart'));
chart.draw(data, chartOptions);
}
google.load('visualization', '1', {packages:['corechart'], callback: drawMultipleTrendlineChart});
</script>
</head>
<body>
<div id="multipleTrendChart"></div>
</body>
I wan't to do it like this image:Image_example
jsfiddle example: http://jsfiddle.net/w3ez9gwb/
Just add more columns of your data:
var data = new google.visualization.DataTable();
data.addColumn('date', 'Date');
data.addColumn('number', 'Sales value A');
data.addColumn('number', 'Sales value B');
data.addRows([
[new Date(2013, 3, 11), 100, 10],
[new Date(2013, 4, 02), 50, 650],
[new Date(2013, 5, 03), 70, 55],
[new Date(2013, 6, 04), 80, 95],
[new Date(2013, 7, 05), 50, 400],
[new Date(2013, 8, 06), 10, 600],
[new Date(2014, 0, 07), 20, 800],
[new Date(2014, 1, 08), 300, 900],
[new Date(2014, 2, 09), 100, 312]
]);
Then add the trendlines to your chart options like so:
var chartOptions = {
tooltip: {
isHtml: true
},
trendlines: {
0: {
color: 'red'
},
1: {
color: 'yellow'
},
},
...
};
Full example: JSFiddle

Make Specific Time Period X-Axis Flot Jquery

I want to make a chart that showing data with 4 month interval (3 period/year).
and i want the x-axis label showing the year and the period like image below:
http://i.stack.imgur.com/eerSy.png
what i've done so far :
var data = [[1262278800000,87.5],[1293814800000,750],[1325350800000,100],[1356973200000,25],[1371229200000,87.5],[1388422800000,0],[1388509200000,375],[1402765200000,100],[1419958800000,1000]];
var tahunsekarang=new Date(2015, 12, 31).getTime();
$.plot("#chartTabamaProduktifitas", [data], {
xaxis: { mode: "time",tickSize: [4, "month"] , timeformat: "%Y",panRange: [1262217600000, tahunsekarang]},
yaxis: {panRange: [0, 1500] },
pan: { interactive: true},
series: {lines: {show: true},points: {show: true}},
});
but since I made it pan: { interactive: true} so when i drag the chart, the tickline is always change value, it made the chartline not fit in the tick line
1) If you want fixed ticks when you drag the chart you have to give a fixed ticks array instead of the tickSize option.
2) To give the Roman number for the trimester you can use a tickFormatter function instead of the timeformat option.
New options object:
xaxis: {
mode: "time",
ticks: ticks,
tickFormatter: function (val, axis) {
var d = new Date(val);
var trimester = '';
for (var i = 1; i <= (1 + d.getMonth() / 4); i++){
trimester += "I";
};
return trimester + "<br>" + d.getFullYear();
},
panRange: [1262217600000, tahunsekarang]
},
See the code snippet below (or this fiddle) for a working example:
var data = [
[1262278800000, 87.5],
[1293814800000, 750],
[1325350800000, 100],
[1356973200000, 25],
[1371229200000, 87.5],
[1388422800000, 0],
[1388509200000, 375],
[1402765200000, 100],
[1419958800000, 1000]
];
var ticks = [
new Date(2010, 0, 1).valueOf(),
new Date(2010, 4, 1).valueOf(),
new Date(2010, 8, 1).valueOf(),
new Date(2011, 0, 1).valueOf(),
new Date(2011, 4, 1).valueOf(),
new Date(2011, 8, 1).valueOf(),
new Date(2012, 0, 1).valueOf(),
new Date(2012, 4, 1).valueOf(),
new Date(2012, 8, 1).valueOf(),
new Date(2013, 0, 1).valueOf(),
new Date(2013, 4, 1).valueOf(),
new Date(2013, 8, 1).valueOf(),
new Date(2014, 0, 1).valueOf(),
new Date(2014, 4, 1).valueOf(),
new Date(2014, 8, 1).valueOf(),
new Date(2015, 0, 1).valueOf(),
new Date(2015, 4, 1).valueOf(),
new Date(2015, 8, 1).valueOf(),
];
var tahunsekarang = new Date(2015, 12, 31).getTime();
$.plot("#chartTabamaProduktifitas", [data], {
xaxis: {
mode: "time",
//tickSize: [4, "month"],
ticks: ticks,
//timeformat: "%Y",
tickFormatter: function (val, axis) {
var d = new Date(val);
var trimester = '';
for (var i = 1; i <= (1 + d.getMonth() / 4); i++){
trimester += "I";
};
return trimester + "<br>" + d.getFullYear();
},
panRange: [1262217600000, tahunsekarang]
},
yaxis: {
panRange: [0, 1500]
},
pan: {
interactive: true
},
series: {
lines: {
show: true
},
points: {
show: true
}
},
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/flot/0.8.2/jquery.flot.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/flot/0.8.2/jquery.flot.time.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/flot/0.8.2/jquery.flot.navigate.min.js"></script>
<div style="height: 400px; width: 600px;" id="chartTabamaProduktifitas"></div>

Categories