I wanted to plot 2 data series.
The first one is a dynamic series of events which has time and height (water level).
The second is a maximum height from t=0 till indef.
I want the first data series with points and the second without points (since it is just a warning line).
So far i tried the following:
pl_data[0].data = plot_data;
pl_data[1].data = plot_maxHeightCoords;
var pl_options = { series: {
lines: { show: true },
points: { show:[true,false] }
}
};
$.plot("#placeholder_flot", pl_data, pl_options);
and this:
pl_options.points:[true,false];
This however wont work. It worked for colors so i figured it should for points too.
I read the documentation but could not find a hint to fix this.
Thank you for any help!
Not sure I'm following your question but I think you want to configure each series separately and not within your plot options.
If the objects are already created:
pl_data[0].data = plot_data;
pl_data[1].data = plot_maxHeightCoords;
pl_data[0].points = {};
pl_data[0].points.show = true;
pl_data[1].points = {};
pl_data[1].points.show = false;
Or recreate the data object:
var pl_data = [ {data: plot_data, points: {show: true}, lines: {show: true}},
{data: plot_maxHeightCoords, points: {show: false}, lines: {show: true}} ];
$.plot("#placeholder_flot", pl_data, {});
This is discussed under the data format section of the documentation.
Related
This is in continued to my question here
I was having a lot of problems in creating highcharts basic charts using CSV data from my local filesystem without using a server/framework and just basic HTML/CSS/JS etc
So, finally, I got an idea to create a chart inside "d3.csv" function wherein we can add highchart functions insdie d3.csv ones
But, there seems to be something very silly wrong, I'm trying with a very basic code and table.
HTML code has only container div element,
Javascript
d3.csv("test.csv", function(data) {
data.forEach(function(d) {
name = d.name,
apples = +d.apples
});
console.log(data[2]);
dataset = data;
//display();
console.log(dataset[0]);
console.log(dataset[0].name);
function push(a)
{
var filter = [];
for (i=0; i<a.length ; i++)
{
filter.push(a[i].apples);
//console.log (filter);
}
return filter;
}
window.apples = push(dataset);
console.log(apples);
$(function () {
$('#container').highcharts({
chart: {
type : 'bar'
},
title: {
text: 'Fruit Consumption'
},
xAxis: {
categories: [dataset[0].name, dataset[1].name]
},
yAxis: {
title: {
text: 'Fruit eaten'
}
},
series: [{
data: apples
}
]
});
})
});
test.csv :
name,apples
John,8
Jane,3
My console is showing "apples" correctly as [8,3]. I'm getting an empty graph on screen with only axes shown and nothing inside and also, x axis and y axis elements are interchanged.
What am I doing wrong here? Is the global variable - apples, not being accessed inside highcharts fucntions?
UPDATE :
Found the answer, but only one number is showing up.
I have 2 more questions :
How do I show the whole series?
Is this a good method to draw highcharts or will I face many issues later?
Found the solution to this, myself, for a change.
Highcharts will expect function to be parsed in their format ( Highcharts error 14 in console)
Changed my function above to this,
for (i=0; i<a.length ; i++)
{
x = a[i].apples;
y = parseFloat(x)
filter.push(y);
}
return filter;
}
window.apples = push(dataset);
And the series part to this :
series: [{
data : [apples]
}
]
This is finally, giving me a graph with one bar (John, 8) now!!
The second number is still not being loaded, if someone wants to help with that, please comment below.
Update :
changed
data : [apples] -> data: apples (Correct format)
Credits : PawelFus
I am making a diagram that should show states in a timeline like diagram. I figured that the best fit for it would be horizontal bar diagram, I added data like this:
series: [{
data: [?],
name: 'state1'
}, {
data: [?],
name: 'state2'
}, {
data: [?],
name: 'state3'
}, {
data: [?],
name: 'state1'
}, {
....
}, {
data: [?],
name: 'state1'
}]
Here's what I'v got:
The chart looks like what I need, but I need to somehow group legends, for example this case there should be only 3 legends: state1, state2, state3.
How can I achieve something like this?
I would suggest a different approach, using the column range series type.
This way you can do this with only three series, with a data point for each time slot, rather than a series for each time slot. This saves from having to manipulate the legend or fake other series level actions.
This is an example I did for an earlier question that demonstrates the method (with only two states):
http://jsfiddle.net/jlbriggs/o9ck2zLn/0/
can easily be adapted to use a datetime axis as well, which it seems you might be going for.
Basing on the answer of #StAlex, I would recommend a similar solution, but without the ECMAScript 5 specific forEach:
var legend = {};
for (var i = 0; i < series.length; i++) {
var bar = series[i];
if (!legend[bar.name]) {
legend[bar.name] = 0;
}
legend[bar.name] += bar.data;
}
I assumed that data is a number. If this is not so, add a comment.
var legends = {};
series.forEach(function(bar){
legends[bar.name] = bar.data;
});
I got an Kendo ui Bar Chart which is filled with an dynamic array.
One time its filled with 12 items and one time its filled with only 1 item.
Now the Bars automatically resizes, when only one item is in the array, the Bar is super big. I know, that there is no "max-width" or "width" property in the configuration.
Is there a workaround for my problem? I.E. dynamic calculation of the gap/space or whatever property? Or even with css or so?
Here is an simple fiddle
var dataset = [1,2,3,3,5,6,8];
var dataOnlyOne = [10]
//gap:0.2
// gap: function(){
return width/12*... // works not
}
Its been a while, and you probably moved on, but I was searching for something similar...
Your problem could be resolved using the below code, where the gap is calculated from the number of items in the data array:
$(function() {
var data = [1,2,3,3,5,6,8,2,3,3,5,6,8];
// var data = [10];
var gap = 8/data.length
$('#chart').kendoChart({
seriesDefaults: {
type: 'column',
stack: true,
},
series: [
{
name: 'dataset',
data: data, // dataOnlyOne
color: 'blue',
gap:gap
}
]
})
});
I'm trying to get zoomin to work for the Flot charts created using following code.
var options = {
yaxis: { min: 0 },
xaxis: { mode: "time" },
series:{
lines: { show: true },
points: { show: true }
},
grid: {
hoverable: true,
clickable: false,
mouseActiveRadius: 30,
backgroundColor: { colors: ["#D1D1D1", "#7A7A7A"] }
},
selection:{mode: "x"}
};
var pdata = [];
for (var key in datasets) {
pdata = [];
pdata.push(datasets[key]);
$.plot( $('<div style="width:1200px;height:600px;"></div>').appendTo('#placeholder'),pdata,options);
$('<h5 align="center">'+datasets[key]['label']+'</h5>').appendTo('#placeholder');
$('<br>').appendTo('#placeholder');
$("#placeholder").UseTooltip();
};
Here I'm creating multiple charts in a loop.
How can I add zoomin feature.
Thank you.
Follow-up to Mark's answer: unique IDs are not really a Flot limitation; that's a requirement of the HTML spec. Browsers generally let you get away with breaking this rule, but it's still not a good idea. Mark's answer is good, but here's one that doesn't require an array-search on every event:
$.each(datasets, function(key, dataset) {
var element = $('<div style="width:1200px;height:600px;"></div>')
.appendTo('#placeholder');
var plot = $.plot(element, [dataset], options);
var plotOptions = plot.getOptions();
element.bind('plotselected', function(event, ranges) {
plotOptions.xaxes[0].min = ranges.xaxis.from;
plotOptions.xaxes[0].max = ranges.xaxis.to;
plot.setupGrid();
plot.draw();
});
};
flot generally expects it's place holder div to have a unique id. You would then use this unique id to assign a specific plotselected event to that plot. The way you have your code structured, though, you are appending the real placeholder div to a parent div as you create your plots. I like your approach so we need to work around flot's limitation.
So, in your plot call give your real placeholder div a class name. This will give us something to bind the plotselected event to. Also you need to save a reference to all the plot objects you've created. I'd just use a global array.
myPlots.push(
$.plot( $('<div class="myPlot" style="width:300px;height:100px;"></div>').appendTo('#placeholder'),pdata,options)
);
Where myPlots is the global array and my class is myPlot.
After this, you can set up the plotselected handler on the jquery selector .myPlots. Next for the tricky part, you need to find your plot object reference inside the handler. The easiest way to do this, I found, is to loop your myPlots array and compare their divs to the div the event happens on:
$(".myPlot").bind("plotselected", function (event, ranges) {
for (var i = 0; i < myPlots.length; i++)
{
var aPlot = myPlots[i];
if (aPlot.getPlaceholder()[0] == event.currentTarget) //this is the correct plot
{
var opts = myPlots[i].getOptions();
opts.xaxes[0].min = ranges.xaxis.from;
opts.xaxes[0].max = ranges.xaxis.to;
myPlots[i].setupGrid();
myPlots[i].draw();
}
}
});
You'll see above I'm redrawing the plot a little different than in the flot examples. I prefer this method since you don't have to remember the data, you adjust the min/max options and you redraw.
Here's a fiddle putting this all together.
I am currently using Highcharts in my website. In one of my charts (a Basic Column chart) I have multiple series, which I can click on the name displayed on the bottom to show/hide.
I can have a lot of series and I would like to limit the number of series to 3 at the same time. It means when it loads the graph, it shows only 3 series and the others are not shown. If I click on a 4th serie, one of the 3 originally present will disappear, so that the number of active serie always remain 3.
I've been looking for it and I found out I needed to do some modifications in the plotOptions.series field and I digged into the Highcharts API reference but didn't found what I wanted. My first attempt at the code would be something like this :
$('#container').highcharts({
plotOptions:{
series: {
var series = this.series;
var nb_of_visible_series = 0;
//Here i count the number of visible series
for(var i=0; i<series.length; i++) {
if(series[i].visible) {
nb_of_visible_series++:
}
}
//If too many series are visible I'll randomly
//hide as many series as necessary
if(nb_of_visible_series>3) {
var nb_of_series_to_hide = nb_of_visible_series-3;
while(nb_of_series_to_hide>0) {
var i=Math.floor(Math.random()*series.length);
if(series[i].visible) {
series[i].hide()
nb_of_series_to_hide--;
}
}
}
}
}
}
So this is the idea but I don't know where to put it for real (not directly in the plotOptions.series field just like this I guess ?). I can put it in plotOptions.series.events.legentItemClick but then it will not be taken into account at the loading of the chart.
I'm looking for some tracks and advices about my code (I'm a JS beginner) and thank you in Advance. And sorry about my poor english.
For sure code you have written wouldn't work. Options for Highcharts should be javascript object, not some thing mixed between variables, options etc.
1) To get displayed on init only three series preprocess data, something like this:
var series = [{ data: [..], name: 'name 1' ..} , { data: [..], name: 'name 2' ..} , ... , {data: [..], name: 'name n'}];
for (var i = 0, len = series.length; i < len; i++) {
series[i].visible = i < 3; //setup variable series.visible to show/hide on init load.
}
$('#container').highcharts({
series: series //pass variable with updated visible option
});
2) As you noticed you need to write your own function for legendItemClick which will check how many series is visible (loop through chart.series and count series.visible == true). Then hide/show specific series using series.hide() / series.show().