I am having an issue with rangeSelector in HighCharts/HighStocks. For some reason, selections are disables. My question is this, how can I make sure that all range selection buttons are active since data is available for a specific range. Here is a example. link
$(function() {
var seriesOptions = [], seriesCounter = 0, names = ['t1'];
function createChart() {
$('#container').highcharts('StockChart', {
loading: {
style: {
backgroundColor: 'silver'
},
labelStyle: {
color: 'white'
}
},
rangeSelector : {
selected : 1
},
yAxis : {
plotLines : [ {
value : 0,
width : 2,
color : 'silver'
} ]
},
plotOptions : {
},
tooltip : {
valueDecimals : 2
},
series : seriesOptions
});
}
$.each(names, function(i, name) {
$.getJSON('https://dl.dropboxusercontent.com/u/34899000/data.json?dt=' + name.toLowerCase(), function(
data) {
seriesOptions[i] = {
name : name,
data : data
};
seriesCounter += 1;
if (seriesCounter === names.length) {
createChart();
}
});
});
});
You must enable the range selector buttons, so in your case you must add an attribute allButtonsEnabled and set it to true
rangeSelector: {
allButtonsEnabled: true,
selected: 1
},
See documentation
http://api.highcharts.com/highstock#rangeSelector
allButtonsEnabled: Boolean
Since 2.0.3
Whether to enable all buttons from the start. By default buttons are
only enabled if the corresponding time range exists on the X axis, but
enabling all buttons allows for dynamically loading different time
ranges. Defaults to false.
In your fiddle enabling all buttons doesn't do anything since the time axis is 1 month which is the minimum range.
Related
I'm trying to create a dynamic flag series to go onto my main chart which is an OHLC series. I want to be able to freely drag each flag and when released, it will snap to the closest y value (either 'High' or 'Low') of the current OHLC bar.
I have been able to acheive this behavior with the following code:
Highcharts.getJSON('https://www.highcharts.com/samples/data/aapl-ohlc.json', function (data) {
var lastDate = data[data.length - 1][0], // Get year of last data point
days = 24 * 36e5; // Milliseconds in a day
// create the chart
Highcharts.stockChart('container', {
tooltip: {
enabled: false
},
rangeSelector: {
selected: 0
},
xAxis :{
crosshair: {
width: 0
}
},
title: {
text: 'AAPL Stock Price'
},
series: [{
type: 'ohlc',
name: 'AAPL Stock Price',
tooltip: {
visible: false
},
data: data,
dataGrouping: {
units: [[
'week', // unit name
[1] // allowed multiples
], [
'month',
[1, 2, 3, 4, 6]
]]
}
},
{
type: 'flags',
align: 'right',
point: {
events: {
drop: snapFlag
}
},
dragDrop: {
draggableX: false,
draggableY: true,
},
data:[{
x:data[data.length - 20][0],
y: data[data.length - 20][2],
title: "A",
text: "1: test",
snapto:'closest',
title: 'A',
}]
}]
});
});
function snapFlag(){
/*
* on drop event, find the nearest OHLC point and snap flag to that point
* this will be the default unless "snapto" property is set to "none"
*/
const old_x = this.x;
const old_y = this.y;
let new_graphic = this.graphic;
let closest_y;
let ohlc_point;
// iterate x values in reverse to find matching ohlc point
ohlc_point = this.series.chart.series[0].points.reverse().filter(function( point){
return point.x === old_x;
})[0];
if(this.snapto === "closest"){
// find the OHLC point that is closest to drop location
closest_y = [ohlc_point.high,ohlc_point.low].reduce(function(prev, curr) {
return (Math.abs(curr - old_y) < Math.abs(prev - old_y) ? curr : prev);
});
}else if(this.snapto !== "float"){
closest_y = ohlc_point[this.snapto]
}else{
closest_y = this.y
}
if(closest_y === ohlc_point.low){
this.graphic.box.element.setAttribute('transform', `translate(0,${this.graphic.box.getBBox().height}) scale(1,-1) translate(0,-${this.graphic.box.getBBox().height})`);
}else{
this.graphic.box.element.removeAttribute('transform');
}
this.update({
y: closest_y
},true,false);
// override the default behavior
return false;
}
<script src="https://code.highcharts.com/stock/highstock.js"></script>
<script src="https://code.highcharts.com/stock/modules/data.js"></script>
<script src="https://code.highcharts.com/stock/modules/exporting.js"></script>
<script src="https://code.highcharts.com/modules/draggable-points.js"></script>
<div id="container" style="height: 400px; min-width: 310px"></div>
And the JSFiddle here
What I'm having trouble with is the SVG transformation. As you can see I have successfully been able to mirror the flag's SVG path about the x-axis such that it does not overlap with the OHLC bar that its attached to. But I am having trouble getting the flag title to adhere to the same translation. I have tried similar methods of directly editing the element that hold the title but have not been able to get the changes to stick.
Any help on this or a different direction I could take to accomplish this would be appreciated. I have been stuck on this small detail for a while!
I think that you should be able to achieve it by translating the graphic.tex separately.
Part of the logic which has been changed:
if (closest_y === ohlc_point.low) {
this.graphic.box.element.setAttribute('transform', `translate(0,${this.graphic.box.getBBox().height}) scale(1,-1) translate(0,-${this.graphic.box.getBBox().height})`);
this.graphic.text.translate(0, this.graphic.box.getBBox().height + this.graphic.text.getBBox().height)
} else {
this.graphic.box.element.removeAttribute('transform');
this.graphic.text.element.removeAttribute('transform');
}
Demo: https://jsfiddle.net/BlackLabel/vy1gzwmd/
I am using normal stacked column Highchart for displaying two items where sometimes any of the item value might become zero. In that case i am not getting next chart elements of that stack displayed instead only one of stack element is displayed. my sample code snippet mentioned below which might not straight forward to reproduce the issue but anyway
chartType : 'chart',
options : {
chart : {
animation : false,
type : 'column',
height : chart_height
},
credits : {
enabled : false
},
legend : {
enabled : true
},
title : {
text : null
},
colors : ['#ED561B', '#50B432'],
plotOptions : {
series : {
stacking : 'normal',
minPointLength : 3
}
},
tooltip : {
useHTML : true
},
xAxis : {
categories : categories,
},
yAxis : {
title : {
text : translations['chart.tooltip_packets'],
useHTML : Language.isRtl() ? Highcharts.hasBidiBug : false
},
opposite : Language.isRtl()
}
},
series : [{
index : '0',
name : 'SSS',
data : [0, 15, 10, 20, 13, 14]
tooltip : {
style : {
color : '#ED561B'
},
headerFormat : '',
pointFormatter : function () {
return '<strong>' + translations['chart.tooltip_packets'] + '</strong><br/>' + this.category + ': ' + this.y;
}
}
}, {
index : '1',
name : 'DDD',
data : [800, 0, 0, 0, 0, 0]
tooltip : {
style : {
color : '#50B432'
},
headerFormat : '',
pointFormatter : function () {
return '<strong>' + translations['chart.tooltip_packets'] + '</strong><br/>' + this.category + ': ' + this.y;
}
}
}
]
My chart looks like
In chart, i have zero value SSS in the first stack and rest of the DDD have zero values but had some value of SSS there which is missing on the chart.
I don't know what is the issue here. Can any one help me?
ok i find out the problem. turn out that you set a size for points that has value 0 with this line
minPointLength: 3
and the values with 10 15 20 are at yAxis starting at 0 but also the point with 0 value are starting at 0 and by you setting minPointLength the points with 0 value are bigger than the others and are on top of the others, so the stacked values are 0-15 and the 0 has extra size that is not stacked. did i explained myself correctly?
I have a line series, on which i display custom data labels for only particular value in the series. On Window resize, the data labels are disappearing from the chart. Is there any solution for this issue.
Thanks in Advance.
My code:
var options = {
chart : {
renderTo : 'container',
type : 'line',
},
xAxis : {
spacingTop: 50,
spacingBottom: 25,
categories : []
},
yAxis : [ {
min: 0,
minRange: 0.1
} ],
plotOptions: {
line:{
dataLabels: {
enabled:true,
defer:false,
formatter: function() {
count++;
if(this.y)
if(batch_info[count]!=0)
return batch_info[count];
}
}
}
},
series : []
};
`
Before window Resize:
After Maximizing Window:
A formatter callback is invoked on every redrawing/resizing, so the most likely scenario is that you do not reset count variable and as the result it accesses the non-existing value, e.g. batch_info[101] when the batch_info.length === 100.
You can use the modulo operator to avoid it:
formatter: function () {
count++;
return batch_info[count % batch_info.length];
}
example: http://jsfiddle.net/ck8zhLmj/1/
but I suggest refactoring the code and dropping the usage of count variable. Instead you can include the information about data label in the series' data or point object.
A solution could be to just reload the highcharts function after a resize.
$(window).resize(function(){
drawVisualization();
});
I am trying to show different charts one on each of the three tabs of the page.
The first tab renders perfectly, but the second and third donĀ“t.
Example of first chart ok
Example of second and Third chart not OK
Every time the tab is selected a $(window).trigger('resize'); is executed so the charts resize. So far they do, but the visual glitch, persist.
When I create the charts for the first time I create them individualy:
var graficoOpcCuenta = { chart: { renderTo: 'graficoPorCuenta' }, rangeSelector: { selected: 1 }, title: { text: 'Rentabilidad Cuenta' }, series: [{ data: [], tooltip: { valueDecimals: 2 } }] };
var graficoOpcCliente = { chart: { renderTo: 'graficoPorCliente' }, rangeSelector: { selected: 1 }, title: { text: 'Rentabilidad Cliente' }, series: [{ data: [], tooltip: { valueDecimals: 2 } }] };
var graficoOpcGrupo = { chart: { renderTo: 'graficoPorGrupo' }, rangeSelector: { selected: 1 }, title: { text: 'Rentabilidad Grupo' }, series: [{ data: [], tooltip: { valueDecimals: 2 } }] };
var graficoPorCuenta = new Highcharts.StockChart(graficoOpcCuenta);
var graficoPorCliente = new Highcharts.StockChart(graficoOpcCliente);
var graficoPorGrupo = new Highcharts.StockChart(graficoOpcGrupo);
Any ideas?
I'm currently using Highstock JS v2.1.9
Update:
Setting the width in chart:{..., width: x} just doesn't make it.
I'm using:
jQuery v2.1.4
Bootstrap 3.3.5
There is no jQuery UI at all
Update 2
Here is my resize:
function resize() {
var height = "some value";
$("#graficoPorCuenta").setGridWidth($("#grillaPorCuenta").width());
$("#graficoPorCliente").setGridWidth($("#grillaPorCliente").width());
$("#graficoPorGrupo").setGridWidth($("#grillaPorGrupo").width());
if ($('#graficoPorCuenta').highcharts() != undefined) {
$('#graficoPorCuenta').highcharts().setSize($("#grillaPorCuenta").width(), height + 120, doAnimation = false);
graficoPorCuenta.reflow();
}
if ($('#graficoPorCliente').highcharts() != undefined) {
$('#graficoPorCliente').highcharts().setSize($("#grillaPorCliente").width(), height + 120, doAnimation = false);
graficoPorCliente.reflow();
}
if ($('#graficoPorGrupo').highcharts() != undefined) {
$('#graficoPorGrupo').highcharts().setSize($("#grillaPorGrupo").width(), height + 120, doAnimation = false);
graficoPorGrupo.reflow();
}
}
Also:
$(window).bind('resize', function () {
resize();
}).trigger('resize');
On Tab change:
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
target = $(e.target).attr("href") // activated tab
if (target == "#tabCuenta") {
graficoPorCuenta.reflow()
}
if (target == "#tabCliente") {
graficoPorCliente.reflow()
}
if (target == "#tabGrupo") {
graficoPorGrupo.reflow()
}
$(window).trigger('resize');
});
It was my bad.
What I was doing wrong:
create the charts
Hiding the divs that contain the chart that not corresponded to the
selected chart tab
triggering window resize
Visual error created
The correct way in my case was
create the charts
triggering window resize
Hiding the divs that contain the chart that not corresponded to the
selected chart tab
Correct visual in all charts.
Changing the order made the trick.
I am working on an application where I am trying to plot a similar graph to what is plotted at Open Weather. I am using the FlotJS library to query their API and plot the graphs.
Here is my code. I apologize for the verbosity.
/*
* RUN PAGE GRAPHS
*/
// load all flot plugins
loadScript("js/plugin/flot/jquery.flot.cust.min.js", function(){
loadScript("js/plugin/flot/jquery.flot.resize.min.js", function(){
loadScript("js/plugin/flot/jquery.flot.time.min.js", function(){
loadScript("js/plugin/flot/jquery.flot.tooltip.min.js", generatePageGraphs);
});
});
});
function generatePageGraphs(){
var fetchWeatherUrl = '//api.openweathermap.org/data/2.5/forecast?lat=' + farmLat + '&lon=' + farmLng;
$.ajax({
method: 'get',
dataType: "jsonp",
url: fetchWeatherUrl,
success: function(response){
var temp = [];
var humidity = [];
var rain = [];
$.each(response.list, function(i, item){
if(moment(item.dt, 'X').isSame(moment(), 'day')){
var temperature = ( ( parseFloat(item.main.temp)-273.15 )*1.80 ).toFixed(0);
temp.push([moment(item.dt, 'X').valueOf(), temperature]);
humidity.push([moment(item.dt, 'X').valueOf(), parseFloat(item.main.humidity)]);
if(item.rain != undefined){
rain.push([moment(item.dt, 'X').valueOf(), parseFloat(item.rain["3h"])]);
}
}
});
var mainWeatherGraphData = [{
label: "Temperature",
data: temp,
lines: {
show: true
},
points: {
show: true
}
},
{
label: "Humidity",
data: humidity,
lines: {
show: true
},
points: {
show: true
},
yaxis: 2
},
{
label: "Rain",
data: rain,
bars: {
show: true,
barWidth: 1000*60*30,
align: 'center'
},
yaxis: 3
}];
var mainWeatherGraphOptions = {
xaxis : {
mode : "time",
},
yaxes : [
{
position: 'left'
},
{
position: 'right'
},
{
position: 'right'
}
],
tooltip : true,
tooltipOpts : {
content : "<b>%s</b> on <b>%x</b> will be <b>%y</b>",
dateFormat : "%y-%m-%d",
defaultTheme : false
},
legend : {
show : true,
noColumns : 1, // number of colums in legend table
labelFormatter : null, // fn: string -> string
labelBoxBorderColor : "#000", // border color for the little label boxes
container : null, // container (as jQuery object) to put legend in, null means default on top of graph
position : "ne", // position of default legend container within plot
margin : [0, 5], // distance from grid edge to default legend container within plot
backgroundColor : "#efefef", // null means auto-detect
backgroundOpacity : 0.4 // set to 0 to avoid background
},
grid : {
hoverable : true,
clickable : true
}
};
var mainWeatherGraph = $.plot($("#mainWeatherGraph"), mainWeatherGraphData, mainWeatherGraphOptions);
}
});
// Daily forecast
fetchForecastUrl = 'http://api.openweathermap.org/data/2.5/forecast/daily?lat=' + farmLat + '&lon=' + farmLng;
$.ajax({
method: 'get',
dataType: "jsonp",
url: fetchForecastUrl,
success: function(response){
var temp = [];
var humidity = [];
var rain = [];
$.each(response.list, function(i, item){
var temperature = ( ( parseFloat(item.temp.day)-273.15 )*1.80 ).toFixed(0);
temp.push([moment(item.dt, 'X').valueOf(), temperature]);
humidity.push([moment(item.dt, 'X').valueOf(), parseFloat(item.humidity)]);
if(item.rain != undefined){
rain.push([moment(item.dt, 'X').valueOf(), parseFloat(item.rain)]);
}
});
var dailyForecastGraphData = [{
label: "Temperature",
data: temp,
lines: {
show: true
},
points: {
show: true
},
},
{
label: "Humidity",
data: humidity,
lines: {
show: true
},
points: {
show: true
},
yaxis: 2
},
{
label: "Rain",
data: rain,
bars: {
show: true,
barWidth: 1000*60*60*8,
align: 'center'
},
yaxis: 3
}];
var dailyForecastGraphOptions = {
xaxis : {
mode : "time",
},
yaxes : [
{
position: 'left'
},
{
position: 'right'
},
{
position: 'right'
}
],
tooltip : true,
tooltipOpts : {
content : "<b>%s</b> on <b>%x</b> will be <b>%y</b>",
dateFormat : "%y-%m-%d",
defaultTheme : false
},
legend : {
show : true,
noColumns : 1, // number of colums in legend table
labelFormatter : null, // fn: string -> string
labelBoxBorderColor : "#000", // border color for the little label boxes
container : null, // container (as jQuery object) to put legend in, null means default on top of graph
position : "ne", // position of default legend container within plot
margin : [0, 5], // distance from grid edge to default legend container within plot
backgroundColor : "#efefef", // null means auto-detect
backgroundOpacity : 0.4 // set to 0 to avoid background
},
grid : {
hoverable : true,
clickable : true
}
};
var dailyForecastGraph = $.plot($("#dailyForecastGraph"), dailyForecastGraphData, dailyForecastGraphOptions);
}
});
}
The two graphs are almost identical except the data which they are portraying.
The main (first) graph has the all the y axis plotted correctly. And we can see the axis for all 3 correctly. The daily (second) graph does have the rain y axis, although the options for them are similar.
Other than this, all tooltips are working fine but the temperature tooltips where I can see the placeholder %y and not the real value.
I have been debugging this code for the past 2 hours and I am not a Flot expert and I am not able to figure what is wrong.
Can anybody look at the code and tell me what is going wrong? Thank you in advance.
While you're creating your temperature data arrays, you need to parse the temperature value as a float. Make sure to parse the value as a float for both graphs. You're doing this for your humidity variable, and that is why the tooltip is working for that series.
var temperature = ((parseFloat(item.main.temp) - 273.15) * 1.80).toFixed(0);
temp.push([moment(item.dt, 'X').valueOf(), parseFloat(temperature)]);
JSFiddle updated with all of the same versions used in the theme you're using: JSFiddle