<p>Example of loading data dynamically with AJAX. Percentage change in GDP (source: <ahref="http://epp.eurostat.ec.europa.eu/tgm/table.do?tab=table&init=1&plugin=1&language=en&pcode=tsieb020">Eurostat</a>). Click the buttons below.</p>
<p>The data is fetched over HTTP, in this case directly from text
files. Usually the URL would point to some web server handler
(e.g. a PHP page or Java/.NET/Python/Ruby on Rails handler) that
extracts it from a database and serializes it to JSON.</p>
button.siblings("span").text("Fetched "+series.label+", first point: "+firstcoordinate);
// Push the new data onto our existing data array
// let's add it to our current data
if(!alreadyFetched[series.label]){
if(!alreadyFetched[series.label]){
alreadyFetched[series.label]=true;
alreadyFetched[series.label]=true;
data.push(series);
data.push(series);
}
}
// and plot all we got
$.plot("#placeholder",data,options);
$.plot(placeholder,data,options);
}
}
$.ajax({
$.ajax({
url:dataurl,
url:dataurl,
type:'GET',
type:"GET",
dataType:'json',
dataType:"json",
success:onDataReceived
success:onDataReceived
});
});
});
});
// Initiate a recurring data update
$("button.dataUpdate").click(function(){
// initiate a recurring data update
$("input.dataUpdate").click(function(){
// reset data
data=[];
data=[];
alreadyFetched={};
alreadyFetched={};
$.plot(placeholder,data,options);
$.plot("#placeholder",data,options);
variteration=0;
variteration=0;
functionfetchData(){
functionfetchData(){
++iteration;
++iteration;
functiononDataReceived(series){
functiononDataReceived(series){
// we get all the data in one go, if we only got partial
// data, we could merge it with what we already got
data=[series];
$.plot($("#placeholder"),data,options);
// Load all the data in one pass; if we only got partial
// data we could merge it with what we already have.
data=[series];
$.plot("#placeholder",data,options);
}
}
// Normally we call the same URL - a script connected to a
// database - but in this case we only have static example
// files, so we need to modify the URL.
$.ajax({
$.ajax({
// usually, we'll just call the same URL, a script
// connected to a database, but in this case we only
// have static example files so we need to modify the
// URL
url:"data-eu-gdp-growth-"+iteration+".json",
url:"data-eu-gdp-growth-"+iteration+".json",
type:'GET',
type:"GET",
dataType:'json',
dataType:"json",
success:onDataReceived
success:onDataReceived
});
});
if(iteration<5)
if(iteration<5){
setTimeout(fetchData,1000);
setTimeout(fetchData,1000);
else{
}else{
data=[];
data=[];
alreadyFetched={};
alreadyFetched={};
}
}
...
@@ -136,8 +111,55 @@ $(function () {
...
@@ -136,8 +111,55 @@ $(function () {
setTimeout(fetchData,1000);
setTimeout(fetchData,1000);
});
});
});
});
</script>
</script>
</head>
<body>
<divid="header">
<h2>AJAX</h2>
</div>
<divid="content">
<divclass="demo-container">
<divid="placeholder"></div>
</div>
<p>Example of loading data dynamically with AJAX. Percentage change in GDP (source: <ahref="http://epp.eurostat.ec.europa.eu/tgm/table.do?tab=table&init=1&plugin=1&language=en&pcode=tsieb020">Eurostat</a>). Click the buttons below:</p>
<p>The data is fetched over HTTP, in this case directly from text files. Usually the URL would point to some web server handler (e.g. a PHP page or Java/.NET/Python/Ruby on Rails handler) that extracts it from a database and serializes it to JSON.</p>
// Draw a little arrow on top of the last label to demonstrate canvas
// drawing
// draw a little arrow on top of the last label to demonstrate
// canvas drawing
varctx=plot.getCanvas().getContext("2d");
varctx=plot.getCanvas().getContext("2d");
ctx.beginPath();
ctx.beginPath();
o.left+=4;
o.left+=4;
...
@@ -68,8 +55,29 @@ $(function () {
...
@@ -68,8 +55,29 @@ $(function () {
ctx.lineTo(o.left,o.top);
ctx.lineTo(o.left,o.top);
ctx.fillStyle="#000";
ctx.fillStyle="#000";
ctx.fill();
ctx.fill();
});
});
</script>
</script>
</head>
<body>
<divid="header">
<h2>Adding Annotations</h2>
</div>
<divid="content">
<divclass="demo-container">
<divid="placeholder"></div>
</div>
<p>Flot has support for simple background decorations such as lines and rectangles. They can be useful for marking up certain areas. You can easily add any HTML you need with standard DOM manipulation, e.g. for labels. For drawing custom shapes there is also direct access to the canvas.</p>
$("#click").text("You clicked the "+axis.direction+axis.n+"axis!")
$("#click").text("You clicked the "+axis.direction+axis.n+"axis!")
});
});
});
});
});
});
</script>
</body>
</script>
</head>
<body>
<divid="header">
<h2>Interacting with axes</h2>
</div>
<divid="content">
<divclass="demo-container">
<divid="placeholder"></div>
</div>
<p>With multiple axes, you sometimes need to interact with them. A simple way to do this is to draw the plot, deduce the axis placements and insert a couple of divs on top to catch events.</p>
<p>There are plenty of options you can set to control the precise looks of
your plot. You can control the ticks on the axes, the legend, the graph
type, etc. The idea is that Flot goes to great lengths to provide sensible
defaults so that you don't have to customize much for a good result.</p>
<script type="text/javascript">
$(function(){
$(function(){
vard1=[];
vard1=[];
for(vari=0;i<Math.PI*2;i+=0.25){
for(vari=0;i<Math.PI*2;i+=0.25){
d1.push([i,Math.sin(i)]);
d1.push([i,Math.sin(i)]);
}
}
vard2=[];
vard2=[];
for(vari=0;i<Math.PI*2;i+=0.25){
for(vari=0;i<Math.PI*2;i+=0.25){
d2.push([i,Math.cos(i)]);
d2.push([i,Math.cos(i)]);
}
}
vard3=[];
vard3=[];
for(vari=0;i<Math.PI*2;i+=0.1){
for(vari=0;i<Math.PI*2;i+=0.1){
d3.push([i,Math.tan(i)]);
d3.push([i,Math.tan(i)]);
}
}
$.plot($("#placeholder"),[
$.plot($("#placeholder"),[
...
@@ -69,9 +57,31 @@ $(function () {
...
@@ -69,9 +57,31 @@ $(function () {
}
}
}
}
});
});
});
});
</script>
</head>
<body>
<divid="header">
<h2>Basic Options</h2>
</div>
<divid="content">
<divclass="demo-container">
<divid="placeholder"></div>
</div>
<p>There are plenty of options you can set to control the precise looks of your plot. You can control the ticks on the axes, the legend, the graph type, etc.</p>
<p>Flot goes to great lengths to provide sensible defaults so that you don't have to customize much for a good-looking result.</p>
<p>Simple example. You don't need to specify much to get an
attractive look. Put in a placeholder, make sure you set its
dimensions (otherwise the plot library will barf) and call the
plot function with the data. The axes are automatically
scaled.</p>
<script type="text/javascript">
$(function(){
vard1=[];
vard1=[];
for(vari=0;i<14;i+=0.5)
for(vari=0;i<14;i+=0.5)
d1.push([i,Math.sin(i)]);
d1.push([i,Math.sin(i)]);
...
@@ -30,9 +19,32 @@ $(function () {
...
@@ -30,9 +19,32 @@ $(function () {
// a null signifies separate line segments
// a null signifies separate line segments
vard3=[[0,12],[7,12],null,[7,2.5],[12,2.5]];
vard3=[[0,12],[7,12],null,[7,2.5],[12,2.5]];
$.plot($("#placeholder"),[d1,d2,d3]);
$.plot("#placeholder",[d1,d2,d3]);
});
});
</script>
</script>
</head>
<body>
<divid="header">
<h2>Basic Usage</h2>
</div>
<divid="content">
<divclass="demo-container">
<divid="placeholder"></div>
</div>
<p>You don't have to do much to get an attractive plot. Create a placeholder, make sure it has dimensions (so Flot knows at what size to draw the plot), then call the plot function with your data.</p>
<p>The Cat's Eye Nebula (<ahref="http://hubblesite.org/gallery/album/nebula/pr2004027a/">picture from Hubble</a>).</p>
<p>With the image plugin, you can plot static images against a set of axes. This is for useful for adding ticks to complex prerendered visualizations. Instead of inputting data points, you specify the images and where their two opposite corners are supposed to be in plot space.</p>
<p>Images represent a little further complication because you need to make sure they are loaded before you can use them (Flot skips incomplete images). The plugin comes with a couple of helpers for doing that.</p>
<p>With the navigate plugin it is easy to add panning and zooming. Drag to pan, double click to zoom (or use the mouse scrollwheel).</p>
<p>The plugin fires events (useful for synchronizing several plots) and adds a couple of public methods so you can easily build a little user interface around it, like the little buttons at the top right in the plot.</p>
<p>Height in centimeters of individuals from the US (2003-2006) as function of age in years (source: <ahref="http://www.cdc.gov/nchs/data/nhsr/nhsr010.pdf">CDC</a>). The 15%-85%, 25%-75% and 50% percentiles are indicated.</p>
<p>For each point of a filled curve, you can specify an arbitrary bottom. As this example illustrates, this can be useful for plotting percentiles. If you have the data sets available without appropriate fill bottoms, you can use the fillbetween plugin to compute the data point bottoms automatically.</p>
// the plugin includes a jQuery plugin for adding resize events to
// The plugin includes a jQuery plugin for adding resize events to any
// any element, let's just add a callback so we can display the
// element. Add a callback so we can display the placeholder size.
// placeholder size
placeholder.resize(function(){
placeholder.resize(function(){
$(".message").text("Placeholder is now "
$(".message").text("Placeholder is now "
+$(this).width()+"x"+$(this).height()
+$(this).width()+"x"+$(this).height()
+" pixels");
+" pixels");
});
});
});
});
</script>
</script>
</head>
<body>
<divid="header">
<h2>Resizing</h2>
</div>
<divid="content"style="width:100%;">
<divclass="demo-container"style="width:100%;">
<divid="placeholder"></div>
</div>
<pclass="message"></p>
<p>Sometimes it makes more sense to just let the plot take up the available space. In that case, we need to redraw the plot each time the placeholder changes its size. If you include the resize plugin, this is handled automatically.</p>
<!--<p>Drag the handles at the bottom and right of the plot to resize it.</p>-->
<p>1000 kg. CO<sub>2</sub> emissions per year per capita for various countries (source: <ahref="http://en.wikipedia.org/wiki/List_of_countries_by_carbon_dioxide_emissions_per_capita">Wikipedia</a>).</p>
$(function(){
<p>Flot supports selections through the selection plugin.
You can enable rectangular selection
or one-dimensional selection if the user should only be able to
select on one axis. Try left-click and drag on the plot above
where selection on the x axis is enabled.</p>
<p>You selected: <spanid="selection"></span></p>
<p>The plot command returns a plot object you can use to control
<p>1000 kg. CO<sub>2</sub> emissions per year per capita for various countries (source: <ahref="http://en.wikipedia.org/wiki/List_of_countries_by_carbon_dioxide_emissions_per_capita">Wikipedia</a>).</p>
<p>Flot supports selections through the selection plugin. You can enable rectangular selection or one-dimensional selection if the user should only be able to select on one axis. Try left-click and drag on the plot above where selection on the x axis is enabled.</p>
<p>You selected: <spanid="selection"></span></p>
<p>The plot command returns a plot object you can use to control the selection. Click the buttons below.</p>
<buttonid="setSelection">Select year 1994</button>
</p>
<p>Selections are really useful for zooming. Just replot the chart with min and max values for the axes set to the values in the "plotselected" event triggered. Enable the checkbox below and select a region again.</p>
<p><label><inputid="zoom"type="checkbox"></input>Zoom to selection.</label></p>
<p>This example shows military budgets for various countries in constant (2005) million US dollars (source: <ahref="http://www.sipri.org/">SIPRI</a>).</p>
<p>Since all data is available client-side, it's pretty easy to make the plot interactive. Try turning countries on and off with the checkboxes next to the plot.</p>
<p>With the stack plugin, you can have Flot stack the
series. This is useful if you wish to display both a total and the
constituents it is made of. The only requirement is that you provide
the input sorted on x.</p>
<pclass="stackControls">
$(function(){
<inputtype="button"value="With stacking">
<inputtype="button"value="Without stacking">
</p>
<pclass="graphControls">
<inputtype="button"value="Bars">
<inputtype="button"value="Lines">
<inputtype="button"value="Lines with steps">
</p>
<script id="source">
$(function(){
vard1=[];
vard1=[];
for(vari=0;i<=10;i+=1)
for(vari=0;i<=10;i+=1){
d1.push([i,parseInt(Math.random()*30)]);
d1.push([i,parseInt(Math.random()*30)]);
}
vard2=[];
vard2=[];
for(vari=0;i<=10;i+=1)
for(vari=0;i<=10;i+=1){
d2.push([i,parseInt(Math.random()*30)]);
d2.push([i,parseInt(Math.random()*30)]);
}
vard3=[];
vard3=[];
for(vari=0;i<=10;i+=1)
for(vari=0;i<=10;i+=1){
d3.push([i,parseInt(Math.random()*30)]);
d3.push([i,parseInt(Math.random()*30)]);
}
varstack=0,bars=true,lines=false,steps=false;
varstack=0,
bars=true,
lines=false,
steps=false;
functionplotWithOptions(){
functionplotWithOptions(){
$.plot($("#placeholder"),[d1,d2,d3],{
$.plot($("#placeholder"),[d1,d2,d3],{
series:{
series:{
stack:stack,
stack:stack,
lines:{show:lines,fill:true,steps:steps},
lines:{
bars:{show:bars,barWidth:0.6}
show:lines,
fill:true,
steps:steps
},
bars:{
show:bars,
barWidth:0.6
}
}
}
});
});
}
}
plotWithOptions();
plotWithOptions();
$(".stackControls input").click(function(e){
$(".stackControls button").click(function(e){
e.preventDefault();
e.preventDefault();
stack=$(this).val()=="With stacking"?true:null;
stack=$(this).text()=="With stacking"?true:null;
plotWithOptions();
plotWithOptions();
});
});
$(".graphControls input").click(function(e){
$(".graphControls button").click(function(e){
e.preventDefault();
e.preventDefault();
bars=$(this).val().indexOf("Bars")!=-1;
bars=$(this).text().indexOf("Bars")!=-1;
lines=$(this).val().indexOf("Lines")!=-1;
lines=$(this).text().indexOf("Lines")!=-1;
steps=$(this).val().indexOf("steps")!=-1;
steps=$(this).text().indexOf("steps")!=-1;
plotWithOptions();
plotWithOptions();
});
});
});
});
</script>
</script>
</head>
<body>
<divid="header">
<h2>Stacking</h2>
</div>
<divid="content">
<divclass="demo-container">
<divid="placeholder"></div>
</div>
<p>With the stack plugin, you can have Flot stack the series. This is useful if you wish to display both a total and the constituents it is made of. The only requirement is that you provide the input sorted on x.</p>
<p>Various point types. Circles are built-in. For other
point types, you can define a little callback function to draw the
symbol; some common ones are available in the symbol plugin.</p>
<script type="text/javascript">
$(function(){
functiongenerate(offset,amplitude){
functiongenerate(offset,amplitude){
varres=[];
varres=[];
varstart=0,end=10;
varstart=0,end=10;
for(vari=0;i<=50;++i){
for(vari=0;i<=50;++i){
varx=start+i/50*(end-start);
varx=start+i/50*(end-start);
res.push([x,amplitude*Math.sin(x+offset)]);
res.push([x,amplitude*Math.sin(x+offset)]);
}
}
returnres;
returnres;
}
}
...
@@ -39,11 +34,39 @@ $(function () {
...
@@ -39,11 +34,39 @@ $(function () {
];
];
$.plot($("#placeholder"),data,{
$.plot($("#placeholder"),data,{
series:{points:{show:true,radius:3}},
series:{
grid:{hoverable:true}
points:{
show:true,
radius:3
}
},
grid:{
hoverable:true
}
});
});
});
});
</script>
</body>
</script>
</head>
<body>
<divid="header">
<h2>Symbols</h2>
</div>
<divid="content">
<divclass="demo-container">
<divid="placeholder"></div>
</div>
<p>Points can be marked in several ways, with circles being the built-in default. For other point types, you can define a callback function to draw the symbol. Some common symbols are available in the symbol plugin.</p>
<p>With the threshold plugin, you can apply a specific color to
the part of a data series below a threshold. This is can be useful
for highlighting negative values, e.g. when displaying net results
or what's in stock.</p>
<pclass="controls">
$(function(){
<inputtype="button"value="Threshold at 5">
<inputtype="button"value="Threshold at 0">
<inputtype="button"value="Threshold at -2.5">
</p>
<script type="text/javascript">
$(function(){
vard1=[];
vard1=[];
for(vari=0;i<=60;i+=1)
for(vari=0;i<=60;i+=1){
d1.push([i,parseInt(Math.random()*30-10)]);
d1.push([i,parseInt(Math.random()*30-10)]);
}
functionplotWithOptions(t){
functionplotWithOptions(t){
$.plot($("#placeholder"),[{
$.plot($("#placeholder"),[{
data:d1,
data:d1,
color:"rgb(30, 180, 20)",
color:"rgb(30, 180, 20)",
threshold:{below:t,color:"rgb(200, 20, 30)"},
threshold:{
lines:{steps:true}
below:t,
}]);
color:"rgb(200, 20, 30)"
},
lines:{
steps:true
}
}]);
}
}
plotWithOptions(0);
plotWithOptions(0);
$(".controls input").click(function(e){
$(".controls button").click(function(e){
e.preventDefault();
e.preventDefault();
vart=parseFloat($(this).val().replace('Threshold at ',''));
vart=parseFloat($(this).text().replace("Threshold at ",""));
plotWithOptions(t);
plotWithOptions(t);
});
});
});
});
</script>
</script>
</head>
<body>
<divid="header">
<h2>Thresholds</h2>
</div>
<divid="content">
<divclass="demo-container">
<divid="placeholder"></div>
</div>
<p>With the threshold plugin, you can apply a specific color to the part of a data series below a threshold. This is can be useful for highlighting negative values, e.g. when displaying net results or what's in stock.</p>
<p>You can add crosshairs that'll track the mouse position, either on both axes or as here on only one.</p>
<p>If you combine it with listening on hover events, you can use it to track the intersection on the curves by interpolating the data points (look at the legend).</p>
<p>This plot shows visitors per day to the Flot homepage, with weekends colored.</p>
<p>The smaller plot is linked to the main plot, so it acts as an overview. Try dragging a selection on either plot, and watch the behavior of the other.</p>
<p>Selection support makes it easy to construct flexible zooming schemes. With a few lines of code, the small overview plot to the right has been connected to the large plot. Try selecting a rectangle on either of them.</p>