Related
Link to JFiddle: http://jsfiddle.net/z24ysp8m/3/
Here is the code in concern:
$(function() {
var chartData = [-5, 5, -10, -20];
var timeStamps = [];
var index = 1;
var pWidth = 25;
$('#b').click(function(){
timeStamps.push(new Date());
var buttonB = document.getElementById('b');
buttonB.disabled = true;
/* if(index == 1){
$('#container').highcharts().xAxis[0].labels.style = {"color":"#6D869F","fontWeight":"bold"};
}*/
if(index <= chartData.length){
$('#container').highcharts().series[0].remove();
$('#container').highcharts().addSeries({pointPlacement: 'on', data: [chartData[index - 1]],
pointWidth: pWidth});
$('#container').highcharts().xAxis[0].setCategories([index]);
setTimeout(function(){index++;}, 2000);
}
if(index < chartData.length){
setTimeout(function(){buttonB.disabled = false;}, 1500);
}else{
setTimeout(function(){buttonB.style.visibility="hidden";}, 1500);
}
if(index == chartData.length - 1){
setTimeout(function(){document.getElementById('b').innerHTML = 'Lasst Period';}, 1500);
}
console.log(timeStamps);
})
// $(document).ready(function () {
Highcharts.setOptions({
lang: {
decimalPoint: ','
},
});
$('#container').highcharts({
chart: {
type: 'column',
width: 170,
marginLeft: 74,
marginRight: 16,
marginBottom: 60
},
title: {
text: ''
},
colors: [
'#0000ff',
],
xAxis: {
title: {
text: ''
// offset: 23
},
gridLineWidth: 1,
startOnTick: true,
tickPixelInterval: 80,
categories: ['Filler'], // used only to make sure that the x-axis of the two charts
// are aligned, not shown on the chart via setting the font color to white
min:0,
max:0,
labels: {
style: {
color: 'white'
}
}
},
yAxis: {
title: {
text: 'Value'
},
min: -20,
max: 20,
tickPixelInterval: 40
},
plotOptions: {
series: {
animation: {
duration: 1000
}
}
},
credits: {
enabled: false
},
tooltip: {
formatter: function () {
return Highcharts.numberFormat(this.y, 2) + '%';
}
},
legend: {
enabled: false
},
exporting: {
enabled: false
},
series: [{
data: [],
pointWidth: pWidth
}]
});
// });
});
I want that the x-axis has no label when the page is loaded (The reason why I added in a filler text with white font is due to the fact that I don't want the size of the chart change upon click of a button). And upon the click of button, the label should be consecutively 1, 2, 3, 4...
Is there anyway around it except for setting marginBottom (which is not very precise)?
You may use .css() method for changing fill color of your text label.
Here you can find information about this method:
http://api.highcharts.com/highcharts#Element.css
Highcharts.each($('#container').highcharts().xAxis[0].labelGroup.element.children, function(p, i) {
$(p).css({
fill: 'red'
});
});
And here you can find simple example how it can work:
http://jsfiddle.net/z24ysp8m/6/
I have a HighCharts Treemap showing a set of categories containing subcategories. The point of the graph is to show how much of the data is in Category A, and how much of Category A is in Subcategory A1.
I have created this as follows:
http://jsfiddle.net/jbcfk93m/
$(function () {
$('#container').highcharts({
series: [{
colorByPoint: true,
layoutAlgorithm: "stripes",
alternateStartingDirection: true,
allowPointSelect: true,
point: {
events: {
click: function () {
alert(this.name + ": " + this.value);
}
}
},
dataLabels: {
},
type: "treemap",
levels: [{
level: 1,
dataLabels: {
enabled: true,
align: 'right',
rotation: 30,
crop: false,
overflow: 'none',
inside: false,
style: {
fontSize: '15px',
fontWeight: 'bold'
}
}
}, {
level: 2,
dataLabels: {
style: {
}
},
layoutAlgorithm: "stripes",
}],
data: [{
// Add parents without values
id: 'CategoryA',
name: 'Category A'
}, {
id: 'CategoryB',
name: 'Category B',
}, {
// And the children with values
name: 'Subcat A1',
value: 4,
parent: 'CategoryA'
}, {
name: 'Subcat A2',
value: 6,
parent: 'CategoryA'
}, {
name: 'Subcat B1',
value: 6,
parent: 'CategoryB'
}, {
name: 'Subcat B2',
value: 2,
parent: 'CategoryB'
}
]
}],
title: {
text: 'Treemap',
margin: 100
},
xAxis: {
min: 0,
max: 100
}
});
});
I want to get both the X- and Y axes in the graph to show percentages so I can more easily see how much of my data is in a certain category.
Does anyone know how to do this?
I didn't find anything about axis on treemaps and i'm not really sure if showing a percentage on X and Y axis would help you that much, because you basically have to multiply the values on X and Y(eg. if your subcat B1 is from 20% to 100% on X axis and from 60% to 100% on the Y axis then you would have to do (100% - 20%) * (100% - 60%) = 32%).
I did implement however a tooltip formatter that will show you the percentage when you hover over the subcategories.
formatter: function () {
var total = 0;
for (var i = 0; i < this.series.data.length; i++)
{
if (this.series.data[i].node.children.length == 0)
total+=this.series.data[i].node.val;
}
var value;
if (this.point.node.children.length == 0)
{
value = this.point.options.value;
}
else
{
value = this.point.node.childrenTotal;
}
return this.key + " " + (value / total) *100 + " %";
}
Here is the working fiddle http://jsfiddle.net/jbcfk93m/4/
Not sure why because I have done it in the past, but I have a Highcharts bar chart and it won't animate. This is the declaration of the chart,
function initializeData() {
$http.get(url).success(function(ret) {
$scope.jsondata = ret;
var newdata = [];
for (x = 0; x < 5; x++) {
newdata.push({
name: setName($scope.jsondata[x].name),
y: $scope.jsondata[x].data[0],
color: getColor($scope.jsondata[x].data[0])
});
}
$scope.chart.series[0].setData(newdata);
});
mainInterval = $interval(updateData, 5000);
}
function updateData() {
$http.get(url).success(function(ret) {
$scope.jsondata = ret;
console.debug("here");
for (x = 0; x < 5; x++) {
$scope.chart.series[0].data[x].update({
y: $scope.jsondata[x].data[0],
color: getColor($scope.jsondata[x].data[0])
});
}
});
}
$scope.chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'bar',
animation: true,
events: {
load: initializeData
}
},
title: {
text: ''
},
xAxis: {
type: 'category',
labels: {
style: {
fontSize: '11px'
}
}
},
yAxis: {
min: 0,
max: 100,
title: {
text: 'Total Score',
align: 'high'
}
},
legend: {
enabled: false
},
tooltip: {
pointFormat: 'Total Score <b>{point.y:.3f}</b>'
},
series: [{
name: 'Active Users',
data: [],
dataLabels: {
enabled: true,
rotation: 30,
style: {
fontSize: '10px',
fontFamily: 'Verdana, sans-serif'
},
format: '{point.y:.3f}', // one decimal
}
}]
});
And as you can see I have animate : true, so I am not sure what is the problem here. I have this older plunker where all of the data is in separate series, but it animates fine. But this is the plunker I am working on and having trouble with. They are like identical basically. In the newer one I broke out the initialization of data into its own method, but that is the only real main difference.
Some edits:
So as I was saying, I have done things this way with an areaspline chart (I know it was said they work a bit different but they are set up identically).
function initializeData() {
$interval.cancel(mainInterval);
$scope.previousPackets = '';
$http.get("https://api.myjson.com/bins/nodx").success(function(returnedData) {
var newdata = [];
var x = (new Date()).getTime();
for (var step = 9; step >= 0; step--) {
newdata.push([x - 1000 * step, 0]);
}
$scope.chart.series[0].setData(newdata);
});
mainInterval = $interval(updateData, 2000);
}
function updateData() {
$http.get(url + acronym + '/latest').success(function(returnedData) {
var x = (new Date()).getTime();
if ($scope.previousPackets != returnedData[0].numPackets) {
$scope.chart.series[0].addPoint([x, returnedData[0].numPackets], true, true);
$scope.previousPackets = returnedData[0].numPackets;
} else {
$scope.chart.series[0].addPoint([x, 0], true, true);
}
});
}
$scope.chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'areaspline',
animation: Highcharts.svg, // don't animate in old IE
marginRight: 10,
events: {
load: initializeData
}
},
title: {
text: ''
},
xAxis: {
type: 'datetime',
tickPixelInterval: 150
},
yAxis: {
title: {
text: 'Packets'
},
plotLines: [{
value: 0,
width: 1,
color: '#d9534f'
}]
},
tooltip: {
formatter: function() {
return Highcharts.numberFormat(this.y) + ' packets<b> | </b>' + Highcharts.dateFormat('%H:%M:%S', this.x);
}
},
legend: {
enabled: false
},
exporting: {
enabled: false
},
series: [{
name: 'Packets',
data: []
}]
});
I also updated the first chunk of code with the initializeData() method and updateData() method which are seemingly identical in both different charts.
It looks like it plays an important role if you provide your data at chart initialization or after. For simplicity I refactored your code a little
function initializeChart(initialData, onload) {
$scope.chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'bar',
animation: true,
events: {
load: onload
}
....
series: [{
name: 'Active Users',
data: initialData,
dataLabels: {
enabled: true,
format: '{point.y:.3f}', // one decimal
}
}]
});
}
function getData(callback) {
$http.get(url).success(function(ret) {
$scope.jsondata = ret;
var newdata = [];
for (x = 0; x < 5; x++) {
newdata.push([setName(ret[x].name), ret[x].data]);
}
callback(newdata);
});
}
As a result your two planks are in essense reduced to two methods below. The first initializes chart with preloaded data and the second updates data in existing chart.
function readDataFirst() {
getData(function(newdata) {
initializeChart(newdata);
});
}
function initializeChartFirst() {
initializeChart([], function() {
getData(function(newdata) {
$scope.chart.series[0].setData(newdata);
})
});
}
The first one animates fine while the second does not. It looks like highcharts skips animation if dataset is not initial and is treated incompatible.
However if you really want to have animation in your current plant (chart first workflow) you can achieve that by initializing first serie with zeros and then with the real data. This case it will be treated as update
function forceAnimationByDoubleInitialization() {
getData(function(newdata) {
initializeChart([]);
var zerodata = newdata.map(function(item) {
return [item[0], 0]
});
$scope.chart.series[0].setData(zerodata);
$scope.chart.series[0].setData(newdata);
});
All these options are available at http://plnkr.co/edit/pZhBJoV7PmjDNRNOj2Uc
So, I discovered that when you have are utilizing highslides in conjuction with highcharts data, its possible to keep clicking new datapoints and have an endless number of modal windows pop up. I wanted to build something that will close an existing highslide popup window if you open a new highslide or if you click anywhere else, either on the screen or on a filter.
I wrote this little function and added it to my beginning statement but it did not work.
<body onclick="javascript:parent.window.hs.close();">
And here is my full example:
The question is, can someone show me an example where I can accomplish my above described behavior?
$(function () {
$('#container').highcharts({
chart: {
type: 'scatter',
zoomType: 'xy'
},
title: {
text: 'Q1 Eanings and Outlook Forecast',
x: -100
},
subtitle: {
text: 'professional',
x:-100
},
xAxis: {
title: {
enabled: false,
text: 'Future Outlook'
},
labels:{formatter: function() {} },
startOnTick: true,
endOnTick: true,
showLastLabel: true
},
yAxis: {
title: {
enabled:false,
text: 'Current Quarter'
},
labels: {
formatter: function() {
//return this.value + ' ';
}
},
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'top',
// x: 100,
y: 70,
floating: false,
backgroundColor: '#FFFFFF',
borderWidth: 1
},
load: function() {
var legend = $('#container .highcharts-legend');
var x = legend.position().left;
var y = legend.position().top - (this.chartHeight - this.plotTop - this.plotHeight - this.options.chart.spacingBottom);
legend.attr({
transform: 'translate(' + x + ',' + y + ')'
});
},
plotOptions: {
scatter: {
marker: {
radius: 5,
states: {
hover: {
enabled: true,
lineColor: 'rgb(100,100,100)'
}
}
},
states: {
hover: {
marker: {
enabled: true
}
}
},
tooltip: {
headerFormat: '<b>{series.name}:</b><br>',
pointFormat: '{point.hover}<br><br><b>Current Q: </b>{point.y}/100<br><b>Outlook: </b>{point.x}/100<br><br><div style="text-align:center;">(click for more detail)</div>'
},
cursor: 'pointer',
point: {
events: {
click: function(event) {
hs.htmlExpand(null, {
pageOrigin: {
x: this.pageX,
y: this.pageY
},
headingText: this.ticker,
maincontentText: '<b>Detail:</b> ' + this.info,
width: 250
});
hs.Expander.prototype.onBeforeClose = function(sender) {
}
},
}
},
events: {
legendItemClick: function(event) {
if (!this.visible)
return true;
var seriesIndex = this.index;
var series = this.chart.series;
for (var i = 0; i < series.length; i++)
{
if (series[i].index != seriesIndex)
{
series[i].visible ? series[i].hide() : series[i].show();
}
}
return false;
}
},
}
},
series: [{
name: 'Weak Outlook (24)',color: 'red',data: [
{x: 40,y:10,ticker:'Michael Kors: (KORS)',info: 'O,.pyjxkne<br>1Q xjkxqs', hover:'Gtext<br>1Qlotatt<br>read more'},
{x: 20,y:50,ticker:'Soeuoeuoeu',info:'Doeuoeuoeull...<br><br>read more'},
{x:0,y:0,ticker:'Zynga: (ZNGA)'},
{x:3,y:4,ticker:'Avid: (AVID)'},
{x:30,y:10,ticker:'JCPenny: (JCP)'},
{x:29,y:25,ticker:'Deckers Outdoor: (DECK)'},
{x:25,y:5,ticker:'Zynga: (ZNGA)'},
{x:6,y:34,ticker:'Avid: (AVID)'},
{x:8,y:27,ticker:'JCPenny: (JCP)'},
{x:14,y:35,ticker:'Deckers Outdoor: (DECK)'},
{x:35,y:23,ticker:'Nutrisystem Corp: (NTRI)'},
]},
{name:'Strong Outlook (25)',color:'green',data:[
{x:100,y:100,ticker:'The Gap: (GPS)'},
{x:72,y:82,ticker:'Sodastream Intl: (SODA)'},
{x:82,y:74,ticker:'Under Armour: (UA)'},
{x:71,y:90,ticker:'Intuitive Surgical: (ISRG)'},
{x:88,y:69,ticker:'McDonalds: (MCD)'},
{x:95,y:87,ticker:'Lumber Liquidators: (LL)'},
{x:77,y:91,ticker:'Apple: (AAPL)'},
{x:96,y:78,ticker:'Walgreen Company: (WAG)'}, {x:100,y:100,ticker:'The Gap: (GPS)'},
{x:73,y:72,ticker:'Sodastream Intl: (SODA)'},
{x:84,y:74,ticker:'Under Armour: (UA)'},
{x:91,y:80,ticker:'Intuitive Surgical: (ISRG)'},
{x:68,y:93,ticker:'McDonalds: (MCD)'},
{x:95,y:67,ticker:'Lumber Liquidators: (LL)'},
{x:76,y:67,ticker:'Apple: (AAPL)'},
{x:79,y:84,ticker:'Walgreen Company: (WAG)'},
]},
{name:'Inline Company Performance (23)',color:'darkgrey',data:[
{x:40,y:44,ticker:'GIII'},
{x:53,y:43,ticker:'BNNY'},
{x:55,y:49,ticker:'SNE'},
{x:57,y:58,ticker:'WTW'},
{x:60,y:60,ticker:'LULU'},
{x:70,y:66,ticker:'FB'},
{x:51,y:24,ticker:'GIII'},
{x:45,y:26,ticker:'FB'},
{x:43,y:53,ticker:'BNNY'},
{x:47,y:59,ticker:'SNE'},
{x:51,y:48,ticker:'WTW'},
{x:56,y:40,ticker:'LULU'},
{x:59,y:52,ticker:'FB'},
{x:0,y:100,ticker:'Nutrisystem Corp: (NTRI)'},
]},
]
});
});
If allowMultipleInstances is set to false, opened expanders will close when you click to open another. Add this right after the included highslide.config.js file:
<script type="text/javascript">
hs.allowMultipleInstances = false;
</script>
I'm just starting out with Highcharts and I'm having a little trouble showing a tooltip for each data item in my graph. At the moment, it just shows a tooltip for the first and last item.
var chart1; // globally available
$(document).ready(function () {
var options = {
chart: {
renderTo: 'AssessmentChart',
marginRight: 100,
marginBottom: 40
},
title: {
text: 'Assessment history',
x: -20 //center
},
subtitle: {
text: 'Assessment history for this patient',
x: -20 //center
},
xAxis: {
type: 'datetime'
},
yAxis: {
title: {
text: 'Score'
},
max: 72,
min: 0
},
tooltip: {
formatter: function() {
return '<b>'+ this.y +'</b>';
}
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'top',
x: -10,
y: 100,
borderWidth: 0
},
series: []
};
// Get the main assessment data...
var dlqiData = [], hdnDlqiData = $("#hdnDlqiData");
if (hdnDlqiData.length > 0) {
var dlqiDataJson = $.parseJSON(hdnDlqiData.val());
$.each(dlqiDataJson, function (i, item) {
dlqiData.push(
{
x: stringToUtcDate(item.dateCreated),
y: item.calculatedScore
}
);
});
options.series.push({
type: 'spline',
name: 'DLQI',
data: dlqiData
});
}
chart1 = new Highcharts.Chart(options);
function stringToUtcDate(datestring) {
var date = datestring.split('/');
return Date.UTC(parseInt(date[2], 10), parseInt(date[1], 10) - 1, parseInt(date[0], 10));
}
});
I'm pulling data in from a hidden form field, so here's a Fiddle showing this in action: http://jsfiddle.net/gfyans/LjRGk/3/
Here's one of the official Fiddle's, http://jsfiddle.net/gh/get/jquery/1.7.2/highslide-software/highcharts.com/tree/master/samples/highcharts/demo/line-basic/, and they manage it OK, but I can't see from that what I'm dong wrong/differently.
I know it'll be something insanely easy, but I can't see it. Can anyone point me in the right direction?
Thanks,
Greg.
You need to have your data in ascending date order if using a datetime x-axis.