Commit bad53abc authored by olau@iola.dk's avatar olau@iola.dk

Revamped internals to add support for extra axes, not just dual (sponsored by Flight Data Services)


git-svn-id: https://flot.googlecode.com/svn/trunk@251 1e0a6537-2640-0410-bfb7-f154510ff394
parent 6f969865
...@@ -15,8 +15,8 @@ you apply to the div, e.g. background images have been reported to be a ...@@ -15,8 +15,8 @@ you apply to the div, e.g. background images have been reported to be a
problem on IE 7. problem on IE 7.
The format of the data is documented below, as is the available The format of the data is documented below, as is the available
options. The "plot" object returned has some methods you can call. options. The plot object returned from the call has some methods you
These are documented separately below. can call. These are documented separately below.
Note that in general Flot gives no guarantees if you change any of the Note that in general Flot gives no guarantees if you change any of the
objects you pass in to the plot function or get out of it since objects you pass in to the plot function or get out of it since
...@@ -65,8 +65,8 @@ The format of a single series object is as follows: ...@@ -65,8 +65,8 @@ The format of a single series object is as follows:
lines: specific lines options lines: specific lines options
bars: specific bars options bars: specific bars options
points: specific points options points: specific points options
xaxis: 1 or 2 xaxis: number
yaxis: 1 or 2 yaxis: number
clickable: boolean clickable: boolean
hoverable: boolean hoverable: boolean
shadowSize: number shadowSize: number
...@@ -93,10 +93,9 @@ The latter is mostly useful if you let the user add and remove series, ...@@ -93,10 +93,9 @@ The latter is mostly useful if you let the user add and remove series,
in which case you can hard-code the color index to prevent the colors in which case you can hard-code the color index to prevent the colors
from jumping around between the series. from jumping around between the series.
The "xaxis" and "yaxis" options specify which axis to use, specify 2 The "xaxis" and "yaxis" options specify which axis to use. The axes
to get the secondary axis (x axis at top or y axis to the right). are numbered from 1 (default), so { yaxis: 2} means that the series
E.g., you can use this to make a dual axis plot by specifying should be plotted against the second y axis.
{ yaxis: 2 } for one data series.
"clickable" and "hoverable" can be set to false to disable "clickable" and "hoverable" can be set to false to disable
interactivity for specific series if interactivity is turned on in interactivity for specific series if interactivity is turned on in
...@@ -172,15 +171,13 @@ ignored. Note that Flot will overwrite the contents of the container. ...@@ -172,15 +171,13 @@ ignored. Note that Flot will overwrite the contents of the container.
Customizing the axes Customizing the axes
==================== ====================
xaxis, yaxis, x2axis, y2axis: { xaxis, yaxis: {
position: "bottom" or "top" or "left" or "right"
mode: null or "time" mode: null or "time"
min: null or number min: null or number
max: null or number max: null or number
autoscaleMargin: null or number autoscaleMargin: null or number
labelWidth: null or number
labelHeight: null or number
transform: null or fn: number -> number transform: null or fn: number -> number
inverseTransform: null or fn: number -> number inverseTransform: null or fn: number -> number
...@@ -189,11 +186,22 @@ Customizing the axes ...@@ -189,11 +186,22 @@ Customizing the axes
minTickSize: number or array minTickSize: number or array
tickFormatter: (fn: number, object -> string) or string tickFormatter: (fn: number, object -> string) or string
tickDecimals: null or number tickDecimals: null or number
labelWidth: null or number
labelHeight: null or number
tickLength: null or number
} }
All axes have the same kind of options. The "mode" option All axes have the same kind of options. The following describes how to
determines how the data is interpreted, the default of null means as configure one axis, see below for what to do if you've got more than
decimal numbers. Use "time" for time series data, see the next section. one x axis or y axis.
The "position" option specifies where the axis is placed, bottom or
top for x axes, left or right for y axes. The "mode" option determines
how the data is interpreted, the default of null means as decimal
numbers. Use "time" for time series data, see the time series data
section.
The options "min"/"max" are the precise minimum/maximum value on the The options "min"/"max" are the precise minimum/maximum value on the
scale. If you don't specify either of them, a value will automatically scale. If you don't specify either of them, a value will automatically
...@@ -207,10 +215,6 @@ specified, the plot will furthermore extend the axis end-point to the ...@@ -207,10 +215,6 @@ specified, the plot will furthermore extend the axis end-point to the
nearest whole tick. The default value is "null" for the x axis and nearest whole tick. The default value is "null" for the x axis and
0.02 for the y axis which seems appropriate for most cases. 0.02 for the y axis which seems appropriate for most cases.
"labelWidth" and "labelHeight" specifies a fixed size of the tick
labels in pixels. They're useful in case you need to align several
plots.
"transform" and "inverseTransform" are callbacks you can put in to "transform" and "inverseTransform" are callbacks you can put in to
change the way the data is drawn. You can design a function to change the way the data is drawn. You can design a function to
compress or expand certain parts of the axis non-linearly, e.g. compress or expand certain parts of the axis non-linearly, e.g.
...@@ -225,7 +229,7 @@ into a natural logarithm axis with the following code: ...@@ -225,7 +229,7 @@ into a natural logarithm axis with the following code:
} }
Note that for finding extrema, Flot assumes that the transform Note that for finding extrema, Flot assumes that the transform
function does not reorder values (monotonicity is assumed). function does not reorder values (it should be monotone).
The inverseTransform is simply the inverse of the transform function The inverseTransform is simply the inverse of the transform function
(so v == inverseTransform(transform(v)) for all relevant v). It is (so v == inverseTransform(transform(v)) for all relevant v). It is
...@@ -282,11 +286,10 @@ axis for trigonometric functions: ...@@ -282,11 +286,10 @@ axis for trigonometric functions:
return res; return res;
} }
You can control how the ticks look like with "tickDecimals", the You can control how the ticks look like with "tickDecimals", the
number of decimals to display (default is auto-detected). number of decimals to display (default is auto-detected).
Alternatively, for ultimate control over how ticks look like you can Alternatively, for ultimate control over how ticks are formatted you can
provide a function to "tickFormatter". The function is passed two provide a function to "tickFormatter". The function is passed two
parameters, the tick value and an "axis" object with information, and parameters, the tick value and an "axis" object with information, and
should return a string. The default formatter looks like this: should return a string. The default formatter looks like this:
...@@ -310,6 +313,49 @@ an example of a custom formatter: ...@@ -310,6 +313,49 @@ an example of a custom formatter:
return val.toFixed(axis.tickDecimals) + " B"; return val.toFixed(axis.tickDecimals) + " B";
} }
"labelWidth" and "labelHeight" specifies a fixed size of the tick
labels in pixels. They're useful in case you need to align several
plots.
"tickLength" is the length of the tick lines in pixels. By default, the
innermost axes will have ticks that extend all across the plot, while
any extra axes use small ticks. A value of null means use the default,
while a number means small ticks of that length - set it to 0 to hide
the lines completely.
Multiple axes
=============
If you need more than one x axis or y axis, you need to specify for
each data series which axis they are to use, as described under the
format of the data series, e.g. { data: [...], yaxis: 2 } specifies
that a series should be plotted against the second y axis.
To actually configure that axis, you can't use the xaxis/yaxis options
directly - instead there are two arrays in the options:
xaxes: []
yaxes: []
Here's an example of configuring a single x axis and two y axes (we
can leave options of the first y axis empty as the defaults are fine):
{
xaxes: [ { position: "top" } ],
yaxes: [ { }, { position: "right", min: 20 } ]
}
The arrays get their default values from the xaxis/yaxis settings, so
say you want to have all y axes start at zero, you can simply specify
yaxis: { min: 0 } instead of adding a min parameter to all the axes.
Generally, the various interfaces in Flot dealing with data points
either accept an xaxis/yaxis parameter to specify which axis number to
use (starting from 1), or lets you specify the coordinate directly as
x2/x3/... or x2axis/x3axis/... instead of "x" or "xaxis".
Time series data Time series data
================ ================
...@@ -547,6 +593,7 @@ Customizing the grid ...@@ -547,6 +593,7 @@ Customizing the grid
backgroundColor: color/gradient or null backgroundColor: color/gradient or null
tickColor: color tickColor: color
labelMargin: number labelMargin: number
axisMargin: number
markings: array of markings or (fn: axes -> array of markings) markings: array of markings or (fn: axes -> array of markings)
borderWidth: number borderWidth: number
borderColor: color or null borderColor: color or null
...@@ -566,19 +613,21 @@ You can turn off the whole grid including tick labels by setting ...@@ -566,19 +613,21 @@ You can turn off the whole grid including tick labels by setting
"show" to false. "aboveData" determines whether the grid is drawn "show" to false. "aboveData" determines whether the grid is drawn
above the data or below (below is default). above the data or below (below is default).
"tickColor" is the color of the ticks and "labelMargin" is the spacing "tickColor" is the color of the ticks, "labelMargin" is the space in
between tick labels and the grid. Note that you can style the tick pixels between tick labels and axis line, and "axisMargin" is the
labels with CSS, e.g. to change the color. They have class "tickLabel". space in pixels between axes when there are two next to each other.
"borderWidth" is the width of the border around the plot. Set it to 0 Note that you can style the tick labels with CSS, e.g. to change the
to disable the border. You can also set "borderColor" if you want the color. They have class "tickLabel". "borderWidth" is the width of the
border to have a different color than the grid lines. border around the plot. Set it to 0 to disable the border. You can
also set "borderColor" if you want the border to have a different
color than the grid lines.
"markings" is used to draw simple lines and rectangular areas in the "markings" is used to draw simple lines and rectangular areas in the
background of the plot. You can either specify an array of ranges on background of the plot. You can either specify an array of ranges on
the form { xaxis: { from, to }, yaxis: { from, to } } (secondary axis the form { xaxis: { from, to }, yaxis: { from, to } } (with multiple
coordinates with x2axis/y2axis) or with a function that returns such axes, you can specify coordinates for other axes instead, e.g. as
an array given the axes for the plot in an object as the first x2axis/x3axis/...) or with a function that returns such an array given
parameter. the axes for the plot in an object as the first parameter.
You can set the color of markings by specifying "color" in the ranges You can set the color of markings by specifying "color" in the ranges
object. Here's an example array: object. Here's an example array:
...@@ -597,7 +646,7 @@ A line is drawn if from and to are the same, e.g. ...@@ -597,7 +646,7 @@ A line is drawn if from and to are the same, e.g.
would draw a line parallel to the x axis at y = 1. You can control the would draw a line parallel to the x axis at y = 1. You can control the
line width with "lineWidth" in the range object. line width with "lineWidth" in the range object.
An example function might look like this: An example function that makes vertical stripes might look like this:
markings: function (axes) { markings: function (axes) {
var markings = []; var markings = [];
...@@ -626,7 +675,7 @@ You can use "plotclick" and "plothover" events like this: ...@@ -626,7 +675,7 @@ You can use "plotclick" and "plothover" events like this:
$("#placeholder").bind("plotclick", function (event, pos, item) { $("#placeholder").bind("plotclick", function (event, pos, item) {
alert("You clicked at " + pos.x + ", " + pos.y); alert("You clicked at " + pos.x + ", " + pos.y);
// secondary axis coordinates if present are in pos.x2, pos.y2, // axis coordinates for other axes, if present, are in pos.x2, pos.x3, ...
// if you need global screen coordinates, they are pos.pageX, pos.pageY // if you need global screen coordinates, they are pos.pageX, pos.pageY
if (item) { if (item) {
...@@ -780,10 +829,10 @@ can call: ...@@ -780,10 +829,10 @@ can call:
- pointOffset({ x: xpos, y: ypos }) - pointOffset({ x: xpos, y: ypos })
Returns the calculated offset of the data point at (x, y) in data Returns the calculated offset of the data point at (x, y) in data
space within the placeholder div. If you are working with dual axes, you space within the placeholder div. If you are working with multiple axes, you
can specify the x and y axis references, e.g. can specify the x and y axis references, e.g.
o = pointOffset({ x: xpos, y: ypos, xaxis: 2, yaxis: 2 }) o = pointOffset({ x: xpos, y: ypos, xaxis: 2, yaxis: 3 })
// o.left and o.top now contains the offset within the div // o.left and o.top now contains the offset within the div
...@@ -811,14 +860,21 @@ Flot to keep track of its state, so be careful. ...@@ -811,14 +860,21 @@ Flot to keep track of its state, so be careful.
- getAxes() - getAxes()
Gets an object with the axes settings as { xaxis, yaxis, x2axis, Gets an object with the axes. The axes are returned as the
y2axis }. attributes of the object, so for instance getAxes().xaxis is the
x axis.
Various things are stuffed inside an axis object, e.g. you could Various things are stuffed inside an axis object, e.g. you could
use getAxes().xaxis.ticks to find out what the ticks are for the use getAxes().xaxis.ticks to find out what the ticks are for the
xaxis. Two other useful attributes are p2c and c2p, functions for xaxis. Two other useful attributes are p2c and c2p, functions for
transforming from data point space to the canvas plot space and transforming from data point space to the canvas plot space and
back. Both returns values that are offset with the plot offset. back. Both returns values that are offset with the plot offset.
Check the Flot source code for the complete set of attributes (or
output an axis with console.log() and inspect it).
With multiple axes, the extra axes are returned as x2axis, x3axis,
etc., e.g. getAxes().y2axis is the second y axis. You can check
y2axis.used to see whether the axis is actually in use or not.
- getPlaceholder() - getPlaceholder()
......
Flot x.x Flot x.x
-------- --------
API changes:
Multiple axes support. Code using dual axes should be changed from
using x2axis/y2axis in the options to using an array. For instance,
{
xaxis: { ... }, x2axis: { ... },
yaxis: { ... }, y2axis: { ... }
}
becomes
{
xaxes: [ { ... }, { ... } ],
yaxes: [ { ... }, { ... } ]
}
Note that if you're just using one axis, continue to use the
xaxis/yaxis directly (it now sets the default settings for the
arrays). Plugins touching the axes must be ported to take the extra
axes into account, a couple of helper functions have been added for
that purpose, check the source.
Changes: Changes:
- Support for specifying a bottom for each point for line charts when - Support for specifying a bottom for each point for line charts when
...@@ -15,9 +39,11 @@ Changes: ...@@ -15,9 +39,11 @@ Changes:
- Stacking plugin can stack horizontal bar charts. - Stacking plugin can stack horizontal bar charts.
- Navigate plugin now redraws the plot while panning instead of only - Navigate plugin now redraws the plot while panning instead of only
after the fact (can be disabled by setting the pan.frameRate option after the fact (can be disabled by setting the pan.frameRate option
to null). Issue 235. to null), raised by lastthemy (issue 235).
- Date formatter now accepts %0m and %0d to get a zero-padded month or - Date formatter now accepts %0m and %0d to get a zero-padded month or
day (issue raised by Maximillian Dornseif). day (issue raised by Maximillian Dornseif).
- Revamped internals to support an unlimited number of axes, not just
dual (sponsored by Flight Data Services, www.flightdataservices.com).
- New hooks: drawSeries - New hooks: drawSeries
Bug fixes: Bug fixes:
......
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
<ul> <ul>
<li><a href="time.html">Plotting time series</a> and <a href="visitors.html">visitors per day with zooming and weekends</a> (with selection plugin)</li> <li><a href="time.html">Plotting time series</a> and <a href="visitors.html">visitors per day with zooming and weekends</a> (with selection plugin)</li>
<li><a href="dual-axis.html">Dual axis support</a></li> <li><a href="multiple-axes.html">Multiple axes</a></li>
<li><a href="thresholding.html">Thresholding the data</a> (with threshold plugin)</li> <li><a href="thresholding.html">Thresholding the data</a> (with threshold plugin)</li>
<li><a href="stacking.html">Stacked charts</a> (with stacking plugin)</li> <li><a href="stacking.html">Stacked charts</a> (with stacking plugin)</li>
<li><a href="percentiles.html">Using filled areas to plot percentiles</a> (with fillbetween plugin)</li> <li><a href="percentiles.html">Using filled areas to plot percentiles</a> (with fillbetween plugin)</li>
......
...@@ -13,26 +13,42 @@ ...@@ -13,26 +13,42 @@
<div id="placeholder" style="width:600px;height:300px;"></div> <div id="placeholder" style="width:600px;height:300px;"></div>
<p>Dual axis support showing the raw oil price in US $/barrel of <p>Multiple axis support showing the raw oil price in US $/barrel of
crude oil (left axis) vs. the exchange rate from US $ to € (right crude oil vs. the exchange rate from US $ to €.</p>
axis).</p>
<p>As illustrated, you can put in secondary y and x axes if you <p>As illustrated, you can put in multiple axes if you
need to. For each data series, simply specify the axis number.</p> need to. For each data series, simply specify the axis number.
In the options, you can then configure where you want the extra
axes to appear.</p>
<p>Position axis <button>left</button> or <button>right</button>.</p>
<script id="source" language="javascript" type="text/javascript"> <script id="source" language="javascript" type="text/javascript">
$(function () { $(function () {
var oilprices = [[1167692400000,61.05], [1167778800000,58.32], [1167865200000,57.35], [1167951600000,56.31], [1168210800000,55.55], [1168297200000,55.64], [1168383600000,54.02], [1168470000000,51.88], [1168556400000,52.99], [1168815600000,52.99], [1168902000000,51.21], [1168988400000,52.24], [1169074800000,50.48], [1169161200000,51.99], [1169420400000,51.13], [1169506800000,55.04], [1169593200000,55.37], [1169679600000,54.23], [1169766000000,55.42], [1170025200000,54.01], [1170111600000,56.97], [1170198000000,58.14], [1170284400000,58.14], [1170370800000,59.02], [1170630000000,58.74], [1170716400000,58.88], [1170802800000,57.71], [1170889200000,59.71], [1170975600000,59.89], [1171234800000,57.81], [1171321200000,59.06], [1171407600000,58.00], [1171494000000,57.99], [1171580400000,59.39], [1171839600000,59.39], [1171926000000,58.07], [1172012400000,60.07], [1172098800000,61.14], [1172444400000,61.39], [1172530800000,61.46], [1172617200000,61.79], [1172703600000,62.00], [1172790000000,60.07], [1173135600000,60.69], [1173222000000,61.82], [1173308400000,60.05], [1173654000000,58.91], [1173740400000,57.93], [1173826800000,58.16], [1173913200000,57.55], [1173999600000,57.11], [1174258800000,56.59], [1174345200000,59.61], [1174518000000,61.69], [1174604400000,62.28], [1174860000000,62.91], [1174946400000,62.93], [1175032800000,64.03], [1175119200000,66.03], [1175205600000,65.87], [1175464800000,64.64], [1175637600000,64.38], [1175724000000,64.28], [1175810400000,64.28], [1176069600000,61.51], [1176156000000,61.89], [1176242400000,62.01], [1176328800000,63.85], [1176415200000,63.63], [1176674400000,63.61], [1176760800000,63.10], [1176847200000,63.13], [1176933600000,61.83], [1177020000000,63.38], [1177279200000,64.58], [1177452000000,65.84], [1177538400000,65.06], [1177624800000,66.46], [1177884000000,64.40], [1178056800000,63.68], [1178143200000,63.19], [1178229600000,61.93], [1178488800000,61.47], [1178575200000,61.55], [1178748000000,61.81], [1178834400000,62.37], [1179093600000,62.46], [1179180000000,63.17], [1179266400000,62.55], [1179352800000,64.94], [1179698400000,66.27], [1179784800000,65.50], [1179871200000,65.77], [1179957600000,64.18], [1180044000000,65.20], [1180389600000,63.15], [1180476000000,63.49], [1180562400000,65.08], [1180908000000,66.30], [1180994400000,65.96], [1181167200000,66.93], [1181253600000,65.98], [1181599200000,65.35], [1181685600000,66.26], [1181858400000,68.00], [1182117600000,69.09], [1182204000000,69.10], [1182290400000,68.19], [1182376800000,68.19], [1182463200000,69.14], [1182722400000,68.19], [1182808800000,67.77], [1182895200000,68.97], [1182981600000,69.57], [1183068000000,70.68], [1183327200000,71.09], [1183413600000,70.92], [1183586400000,71.81], [1183672800000,72.81], [1183932000000,72.19], [1184018400000,72.56], [1184191200000,72.50], [1184277600000,74.15], [1184623200000,75.05], [1184796000000,75.92], [1184882400000,75.57], [1185141600000,74.89], [1185228000000,73.56], [1185314400000,75.57], [1185400800000,74.95], [1185487200000,76.83], [1185832800000,78.21], [1185919200000,76.53], [1186005600000,76.86], [1186092000000,76.00], [1186437600000,71.59], [1186696800000,71.47], [1186956000000,71.62], [1187042400000,71.00], [1187301600000,71.98], [1187560800000,71.12], [1187647200000,69.47], [1187733600000,69.26], [1187820000000,69.83], [1187906400000,71.09], [1188165600000,71.73], [1188338400000,73.36], [1188511200000,74.04], [1188856800000,76.30], [1189116000000,77.49], [1189461600000,78.23], [1189548000000,79.91], [1189634400000,80.09], [1189720800000,79.10], [1189980000000,80.57], [1190066400000,81.93], [1190239200000,83.32], [1190325600000,81.62], [1190584800000,80.95], [1190671200000,79.53], [1190757600000,80.30], [1190844000000,82.88], [1190930400000,81.66], [1191189600000,80.24], [1191276000000,80.05], [1191362400000,79.94], [1191448800000,81.44], [1191535200000,81.22], [1191794400000,79.02], [1191880800000,80.26], [1191967200000,80.30], [1192053600000,83.08], [1192140000000,83.69], [1192399200000,86.13], [1192485600000,87.61], [1192572000000,87.40], [1192658400000,89.47], [1192744800000,88.60], [1193004000000,87.56], [1193090400000,87.56], [1193176800000,87.10], [1193263200000,91.86], [1193612400000,93.53], [1193698800000,94.53], [1193871600000,95.93], [1194217200000,93.98], [1194303600000,96.37], [1194476400000,95.46], [1194562800000,96.32], [1195081200000,93.43], [1195167600000,95.10], [1195426800000,94.64], [1195513200000,95.10], [1196031600000,97.70], [1196118000000,94.42], [1196204400000,90.62], [1196290800000,91.01], [1196377200000,88.71], [1196636400000,88.32], [1196809200000,90.23], [1196982000000,88.28], [1197241200000,87.86], [1197327600000,90.02], [1197414000000,92.25], [1197586800000,90.63], [1197846000000,90.63], [1197932400000,90.49], [1198018800000,91.24], [1198105200000,91.06], [1198191600000,90.49], [1198710000000,96.62], [1198796400000,96.00], [1199142000000,99.62], [1199314800000,99.18], [1199401200000,95.09], [1199660400000,96.33], [1199833200000,95.67], [1200351600000,91.90], [1200438000000,90.84], [1200524400000,90.13], [1200610800000,90.57], [1200956400000,89.21], [1201042800000,86.99], [1201129200000,89.85], [1201474800000,90.99], [1201561200000,91.64], [1201647600000,92.33], [1201734000000,91.75], [1202079600000,90.02], [1202166000000,88.41], [1202252400000,87.14], [1202338800000,88.11], [1202425200000,91.77], [1202770800000,92.78], [1202857200000,93.27], [1202943600000,95.46], [1203030000000,95.46], [1203289200000,101.74], [1203462000000,98.81], [1203894000000,100.88], [1204066800000,99.64], [1204153200000,102.59], [1204239600000,101.84], [1204498800000,99.52], [1204585200000,99.52], [1204671600000,104.52], [1204758000000,105.47], [1204844400000,105.15], [1205103600000,108.75], [1205276400000,109.92], [1205362800000,110.33], [1205449200000,110.21], [1205708400000,105.68], [1205967600000,101.84], [1206313200000,100.86], [1206399600000,101.22], [1206486000000,105.90], [1206572400000,107.58], [1206658800000,105.62], [1206914400000,101.58], [1207000800000,100.98], [1207173600000,103.83], [1207260000000,106.23], [1207605600000,108.50], [1207778400000,110.11], [1207864800000,110.14], [1208210400000,113.79], [1208296800000,114.93], [1208383200000,114.86], [1208728800000,117.48], [1208815200000,118.30], [1208988000000,116.06], [1209074400000,118.52], [1209333600000,118.75], [1209420000000,113.46], [1209592800000,112.52], [1210024800000,121.84], [1210111200000,123.53], [1210197600000,123.69], [1210543200000,124.23], [1210629600000,125.80], [1210716000000,126.29], [1211148000000,127.05], [1211320800000,129.07], [1211493600000,132.19], [1211839200000,128.85], [1212357600000,127.76], [1212703200000,138.54], [1212962400000,136.80], [1213135200000,136.38], [1213308000000,134.86], [1213653600000,134.01], [1213740000000,136.68], [1213912800000,135.65], [1214172000000,134.62], [1214258400000,134.62], [1214344800000,134.62], [1214431200000,139.64], [1214517600000,140.21], [1214776800000,140.00], [1214863200000,140.97], [1214949600000,143.57], [1215036000000,145.29], [1215381600000,141.37], [1215468000000,136.04], [1215727200000,146.40], [1215986400000,145.18], [1216072800000,138.74], [1216159200000,134.60], [1216245600000,129.29], [1216332000000,130.65], [1216677600000,127.95], [1216850400000,127.95], [1217282400000,122.19], [1217455200000,124.08], [1217541600000,125.10], [1217800800000,121.41], [1217887200000,119.17], [1217973600000,118.58], [1218060000000,120.02], [1218405600000,114.45], [1218492000000,113.01], [1218578400000,116.00], [1218751200000,113.77], [1219010400000,112.87], [1219096800000,114.53], [1219269600000,114.98], [1219356000000,114.98], [1219701600000,116.27], [1219788000000,118.15], [1219874400000,115.59], [1219960800000,115.46], [1220306400000,109.71], [1220392800000,109.35], [1220565600000,106.23], [1220824800000,106.34]]; var oilprices = [[1167692400000,61.05], [1167778800000,58.32], [1167865200000,57.35], [1167951600000,56.31], [1168210800000,55.55], [1168297200000,55.64], [1168383600000,54.02], [1168470000000,51.88], [1168556400000,52.99], [1168815600000,52.99], [1168902000000,51.21], [1168988400000,52.24], [1169074800000,50.48], [1169161200000,51.99], [1169420400000,51.13], [1169506800000,55.04], [1169593200000,55.37], [1169679600000,54.23], [1169766000000,55.42], [1170025200000,54.01], [1170111600000,56.97], [1170198000000,58.14], [1170284400000,58.14], [1170370800000,59.02], [1170630000000,58.74], [1170716400000,58.88], [1170802800000,57.71], [1170889200000,59.71], [1170975600000,59.89], [1171234800000,57.81], [1171321200000,59.06], [1171407600000,58.00], [1171494000000,57.99], [1171580400000,59.39], [1171839600000,59.39], [1171926000000,58.07], [1172012400000,60.07], [1172098800000,61.14], [1172444400000,61.39], [1172530800000,61.46], [1172617200000,61.79], [1172703600000,62.00], [1172790000000,60.07], [1173135600000,60.69], [1173222000000,61.82], [1173308400000,60.05], [1173654000000,58.91], [1173740400000,57.93], [1173826800000,58.16], [1173913200000,57.55], [1173999600000,57.11], [1174258800000,56.59], [1174345200000,59.61], [1174518000000,61.69], [1174604400000,62.28], [1174860000000,62.91], [1174946400000,62.93], [1175032800000,64.03], [1175119200000,66.03], [1175205600000,65.87], [1175464800000,64.64], [1175637600000,64.38], [1175724000000,64.28], [1175810400000,64.28], [1176069600000,61.51], [1176156000000,61.89], [1176242400000,62.01], [1176328800000,63.85], [1176415200000,63.63], [1176674400000,63.61], [1176760800000,63.10], [1176847200000,63.13], [1176933600000,61.83], [1177020000000,63.38], [1177279200000,64.58], [1177452000000,65.84], [1177538400000,65.06], [1177624800000,66.46], [1177884000000,64.40], [1178056800000,63.68], [1178143200000,63.19], [1178229600000,61.93], [1178488800000,61.47], [1178575200000,61.55], [1178748000000,61.81], [1178834400000,62.37], [1179093600000,62.46], [1179180000000,63.17], [1179266400000,62.55], [1179352800000,64.94], [1179698400000,66.27], [1179784800000,65.50], [1179871200000,65.77], [1179957600000,64.18], [1180044000000,65.20], [1180389600000,63.15], [1180476000000,63.49], [1180562400000,65.08], [1180908000000,66.30], [1180994400000,65.96], [1181167200000,66.93], [1181253600000,65.98], [1181599200000,65.35], [1181685600000,66.26], [1181858400000,68.00], [1182117600000,69.09], [1182204000000,69.10], [1182290400000,68.19], [1182376800000,68.19], [1182463200000,69.14], [1182722400000,68.19], [1182808800000,67.77], [1182895200000,68.97], [1182981600000,69.57], [1183068000000,70.68], [1183327200000,71.09], [1183413600000,70.92], [1183586400000,71.81], [1183672800000,72.81], [1183932000000,72.19], [1184018400000,72.56], [1184191200000,72.50], [1184277600000,74.15], [1184623200000,75.05], [1184796000000,75.92], [1184882400000,75.57], [1185141600000,74.89], [1185228000000,73.56], [1185314400000,75.57], [1185400800000,74.95], [1185487200000,76.83], [1185832800000,78.21], [1185919200000,76.53], [1186005600000,76.86], [1186092000000,76.00], [1186437600000,71.59], [1186696800000,71.47], [1186956000000,71.62], [1187042400000,71.00], [1187301600000,71.98], [1187560800000,71.12], [1187647200000,69.47], [1187733600000,69.26], [1187820000000,69.83], [1187906400000,71.09], [1188165600000,71.73], [1188338400000,73.36], [1188511200000,74.04], [1188856800000,76.30], [1189116000000,77.49], [1189461600000,78.23], [1189548000000,79.91], [1189634400000,80.09], [1189720800000,79.10], [1189980000000,80.57], [1190066400000,81.93], [1190239200000,83.32], [1190325600000,81.62], [1190584800000,80.95], [1190671200000,79.53], [1190757600000,80.30], [1190844000000,82.88], [1190930400000,81.66], [1191189600000,80.24], [1191276000000,80.05], [1191362400000,79.94], [1191448800000,81.44], [1191535200000,81.22], [1191794400000,79.02], [1191880800000,80.26], [1191967200000,80.30], [1192053600000,83.08], [1192140000000,83.69], [1192399200000,86.13], [1192485600000,87.61], [1192572000000,87.40], [1192658400000,89.47], [1192744800000,88.60], [1193004000000,87.56], [1193090400000,87.56], [1193176800000,87.10], [1193263200000,91.86], [1193612400000,93.53], [1193698800000,94.53], [1193871600000,95.93], [1194217200000,93.98], [1194303600000,96.37], [1194476400000,95.46], [1194562800000,96.32], [1195081200000,93.43], [1195167600000,95.10], [1195426800000,94.64], [1195513200000,95.10], [1196031600000,97.70], [1196118000000,94.42], [1196204400000,90.62], [1196290800000,91.01], [1196377200000,88.71], [1196636400000,88.32], [1196809200000,90.23], [1196982000000,88.28], [1197241200000,87.86], [1197327600000,90.02], [1197414000000,92.25], [1197586800000,90.63], [1197846000000,90.63], [1197932400000,90.49], [1198018800000,91.24], [1198105200000,91.06], [1198191600000,90.49], [1198710000000,96.62], [1198796400000,96.00], [1199142000000,99.62], [1199314800000,99.18], [1199401200000,95.09], [1199660400000,96.33], [1199833200000,95.67], [1200351600000,91.90], [1200438000000,90.84], [1200524400000,90.13], [1200610800000,90.57], [1200956400000,89.21], [1201042800000,86.99], [1201129200000,89.85], [1201474800000,90.99], [1201561200000,91.64], [1201647600000,92.33], [1201734000000,91.75], [1202079600000,90.02], [1202166000000,88.41], [1202252400000,87.14], [1202338800000,88.11], [1202425200000,91.77], [1202770800000,92.78], [1202857200000,93.27], [1202943600000,95.46], [1203030000000,95.46], [1203289200000,101.74], [1203462000000,98.81], [1203894000000,100.88], [1204066800000,99.64], [1204153200000,102.59], [1204239600000,101.84], [1204498800000,99.52], [1204585200000,99.52], [1204671600000,104.52], [1204758000000,105.47], [1204844400000,105.15], [1205103600000,108.75], [1205276400000,109.92], [1205362800000,110.33], [1205449200000,110.21], [1205708400000,105.68], [1205967600000,101.84], [1206313200000,100.86], [1206399600000,101.22], [1206486000000,105.90], [1206572400000,107.58], [1206658800000,105.62], [1206914400000,101.58], [1207000800000,100.98], [1207173600000,103.83], [1207260000000,106.23], [1207605600000,108.50], [1207778400000,110.11], [1207864800000,110.14], [1208210400000,113.79], [1208296800000,114.93], [1208383200000,114.86], [1208728800000,117.48], [1208815200000,118.30], [1208988000000,116.06], [1209074400000,118.52], [1209333600000,118.75], [1209420000000,113.46], [1209592800000,112.52], [1210024800000,121.84], [1210111200000,123.53], [1210197600000,123.69], [1210543200000,124.23], [1210629600000,125.80], [1210716000000,126.29], [1211148000000,127.05], [1211320800000,129.07], [1211493600000,132.19], [1211839200000,128.85], [1212357600000,127.76], [1212703200000,138.54], [1212962400000,136.80], [1213135200000,136.38], [1213308000000,134.86], [1213653600000,134.01], [1213740000000,136.68], [1213912800000,135.65], [1214172000000,134.62], [1214258400000,134.62], [1214344800000,134.62], [1214431200000,139.64], [1214517600000,140.21], [1214776800000,140.00], [1214863200000,140.97], [1214949600000,143.57], [1215036000000,145.29], [1215381600000,141.37], [1215468000000,136.04], [1215727200000,146.40], [1215986400000,145.18], [1216072800000,138.74], [1216159200000,134.60], [1216245600000,129.29], [1216332000000,130.65], [1216677600000,127.95], [1216850400000,127.95], [1217282400000,122.19], [1217455200000,124.08], [1217541600000,125.10], [1217800800000,121.41], [1217887200000,119.17], [1217973600000,118.58], [1218060000000,120.02], [1218405600000,114.45], [1218492000000,113.01], [1218578400000,116.00], [1218751200000,113.77], [1219010400000,112.87], [1219096800000,114.53], [1219269600000,114.98], [1219356000000,114.98], [1219701600000,116.27], [1219788000000,118.15], [1219874400000,115.59], [1219960800000,115.46], [1220306400000,109.71], [1220392800000,109.35], [1220565600000,106.23], [1220824800000,106.34]];
var exchangerates = [[1167606000000,0.7580], [1167692400000,0.7580], [1167778800000,0.75470], [1167865200000,0.75490], [1167951600000,0.76130], [1168038000000,0.76550], [1168124400000,0.76930], [1168210800000,0.76940], [1168297200000,0.76880], [1168383600000,0.76780], [1168470000000,0.77080], [1168556400000,0.77270], [1168642800000,0.77490], [1168729200000,0.77410], [1168815600000,0.77410], [1168902000000,0.77320], [1168988400000,0.77270], [1169074800000,0.77370], [1169161200000,0.77240], [1169247600000,0.77120], [1169334000000,0.7720], [1169420400000,0.77210], [1169506800000,0.77170], [1169593200000,0.77040], [1169679600000,0.7690], [1169766000000,0.77110], [1169852400000,0.7740], [1169938800000,0.77450], [1170025200000,0.77450], [1170111600000,0.7740], [1170198000000,0.77160], [1170284400000,0.77130], [1170370800000,0.76780], [1170457200000,0.76880], [1170543600000,0.77180], [1170630000000,0.77180], [1170716400000,0.77280], [1170802800000,0.77290], [1170889200000,0.76980], [1170975600000,0.76850], [1171062000000,0.76810], [1171148400000,0.7690], [1171234800000,0.7690], [1171321200000,0.76980], [1171407600000,0.76990], [1171494000000,0.76510], [1171580400000,0.76130], [1171666800000,0.76160], [1171753200000,0.76140], [1171839600000,0.76140], [1171926000000,0.76070], [1172012400000,0.76020], [1172098800000,0.76110], [1172185200000,0.76220], [1172271600000,0.76150], [1172358000000,0.75980], [1172444400000,0.75980], [1172530800000,0.75920], [1172617200000,0.75730], [1172703600000,0.75660], [1172790000000,0.75670], [1172876400000,0.75910], [1172962800000,0.75820], [1173049200000,0.75850], [1173135600000,0.76130], [1173222000000,0.76310], [1173308400000,0.76150], [1173394800000,0.760], [1173481200000,0.76130], [1173567600000,0.76270], [1173654000000,0.76270], [1173740400000,0.76080], [1173826800000,0.75830], [1173913200000,0.75750], [1173999600000,0.75620], [1174086000000,0.7520], [1174172400000,0.75120], [1174258800000,0.75120], [1174345200000,0.75170], [1174431600000,0.7520], [1174518000000,0.75110], [1174604400000,0.7480], [1174690800000,0.75090], [1174777200000,0.75310], [1174860000000,0.75310], [1174946400000,0.75270], [1175032800000,0.74980], [1175119200000,0.74930], [1175205600000,0.75040], [1175292000000,0.750], [1175378400000,0.74910], [1175464800000,0.74910], [1175551200000,0.74850], [1175637600000,0.74840], [1175724000000,0.74920], [1175810400000,0.74710], [1175896800000,0.74590], [1175983200000,0.74770], [1176069600000,0.74770], [1176156000000,0.74830], [1176242400000,0.74580], [1176328800000,0.74480], [1176415200000,0.7430], [1176501600000,0.73990], [1176588000000,0.73950], [1176674400000,0.73950], [1176760800000,0.73780], [1176847200000,0.73820], [1176933600000,0.73620], [1177020000000,0.73550], [1177106400000,0.73480], [1177192800000,0.73610], [1177279200000,0.73610], [1177365600000,0.73650], [1177452000000,0.73620], [1177538400000,0.73310], [1177624800000,0.73390], [1177711200000,0.73440], [1177797600000,0.73270], [1177884000000,0.73270], [1177970400000,0.73360], [1178056800000,0.73330], [1178143200000,0.73590], [1178229600000,0.73590], [1178316000000,0.73720], [1178402400000,0.7360], [1178488800000,0.7360], [1178575200000,0.7350], [1178661600000,0.73650], [1178748000000,0.73840], [1178834400000,0.73950], [1178920800000,0.74130], [1179007200000,0.73970], [1179093600000,0.73960], [1179180000000,0.73850], [1179266400000,0.73780], [1179352800000,0.73660], [1179439200000,0.740], [1179525600000,0.74110], [1179612000000,0.74060], [1179698400000,0.74050], [1179784800000,0.74140], [1179871200000,0.74310], [1179957600000,0.74310], [1180044000000,0.74380], [1180130400000,0.74430], [1180216800000,0.74430], [1180303200000,0.74430], [1180389600000,0.74340], [1180476000000,0.74290], [1180562400000,0.74420], [1180648800000,0.7440], [1180735200000,0.74390], [1180821600000,0.74370], [1180908000000,0.74370], [1180994400000,0.74290], [1181080800000,0.74030], [1181167200000,0.73990], [1181253600000,0.74180], [1181340000000,0.74680], [1181426400000,0.7480], [1181512800000,0.7480], [1181599200000,0.7490], [1181685600000,0.74940], [1181772000000,0.75220], [1181858400000,0.75150], [1181944800000,0.75020], [1182031200000,0.74720], [1182117600000,0.74720], [1182204000000,0.74620], [1182290400000,0.74550], [1182376800000,0.74490], [1182463200000,0.74670], [1182549600000,0.74580], [1182636000000,0.74270], [1182722400000,0.74270], [1182808800000,0.7430], [1182895200000,0.74290], [1182981600000,0.7440], [1183068000000,0.7430], [1183154400000,0.74220], [1183240800000,0.73880], [1183327200000,0.73880], [1183413600000,0.73690], [1183500000000,0.73450], [1183586400000,0.73450], [1183672800000,0.73450], [1183759200000,0.73520], [1183845600000,0.73410], [1183932000000,0.73410], [1184018400000,0.7340], [1184104800000,0.73240], [1184191200000,0.72720], [1184277600000,0.72640], [1184364000000,0.72550], [1184450400000,0.72580], [1184536800000,0.72580], [1184623200000,0.72560], [1184709600000,0.72570], [1184796000000,0.72470], [1184882400000,0.72430], [1184968800000,0.72440], [1185055200000,0.72350], [1185141600000,0.72350], [1185228000000,0.72350], [1185314400000,0.72350], [1185400800000,0.72620], [1185487200000,0.72880], [1185573600000,0.73010], [1185660000000,0.73370], [1185746400000,0.73370], [1185832800000,0.73240], [1185919200000,0.72970], [1186005600000,0.73170], [1186092000000,0.73150], [1186178400000,0.72880], [1186264800000,0.72630], [1186351200000,0.72630], [1186437600000,0.72420], [1186524000000,0.72530], [1186610400000,0.72640], [1186696800000,0.7270], [1186783200000,0.73120], [1186869600000,0.73050], [1186956000000,0.73050], [1187042400000,0.73180], [1187128800000,0.73580], [1187215200000,0.74090], [1187301600000,0.74540], [1187388000000,0.74370], [1187474400000,0.74240], [1187560800000,0.74240], [1187647200000,0.74150], [1187733600000,0.74190], [1187820000000,0.74140], [1187906400000,0.73770], [1187992800000,0.73550], [1188079200000,0.73150], [1188165600000,0.73150], [1188252000000,0.7320], [1188338400000,0.73320], [1188424800000,0.73460], [1188511200000,0.73280], [1188597600000,0.73230], [1188684000000,0.7340], [1188770400000,0.7340], [1188856800000,0.73360], [1188943200000,0.73510], [1189029600000,0.73460], [1189116000000,0.73210], [1189202400000,0.72940], [1189288800000,0.72660], [1189375200000,0.72660], [1189461600000,0.72540], [1189548000000,0.72420], [1189634400000,0.72130], [1189720800000,0.71970], [1189807200000,0.72090], [1189893600000,0.7210], [1189980000000,0.7210], [1190066400000,0.7210], [1190152800000,0.72090], [1190239200000,0.71590], [1190325600000,0.71330], [1190412000000,0.71050], [1190498400000,0.70990], [1190584800000,0.70990], [1190671200000,0.70930], [1190757600000,0.70930], [1190844000000,0.70760], [1190930400000,0.7070], [1191016800000,0.70490], [1191103200000,0.70120], [1191189600000,0.70110], [1191276000000,0.70190], [1191362400000,0.70460], [1191448800000,0.70630], [1191535200000,0.70890], [1191621600000,0.70770], [1191708000000,0.70770], [1191794400000,0.70770], [1191880800000,0.70910], [1191967200000,0.71180], [1192053600000,0.70790], [1192140000000,0.70530], [1192226400000,0.7050], [1192312800000,0.70550], [1192399200000,0.70550], [1192485600000,0.70450], [1192572000000,0.70510], [1192658400000,0.70510], [1192744800000,0.70170], [1192831200000,0.70], [1192917600000,0.69950], [1193004000000,0.69940], [1193090400000,0.70140], [1193176800000,0.70360], [1193263200000,0.70210], [1193349600000,0.70020], [1193436000000,0.69670], [1193522400000,0.6950], [1193612400000,0.6950], [1193698800000,0.69390], [1193785200000,0.6940], [1193871600000,0.69220], [1193958000000,0.69190], [1194044400000,0.69140], [1194130800000,0.68940], [1194217200000,0.68910], [1194303600000,0.69040], [1194390000000,0.6890], [1194476400000,0.68340], [1194562800000,0.68230], [1194649200000,0.68070], [1194735600000,0.68150], [1194822000000,0.68150], [1194908400000,0.68470], [1194994800000,0.68590], [1195081200000,0.68220], [1195167600000,0.68270], [1195254000000,0.68370], [1195340400000,0.68230], [1195426800000,0.68220], [1195513200000,0.68220], [1195599600000,0.67920], [1195686000000,0.67460], [1195772400000,0.67350], [1195858800000,0.67310], [1195945200000,0.67420], [1196031600000,0.67440], [1196118000000,0.67390], [1196204400000,0.67310], [1196290800000,0.67610], [1196377200000,0.67610], [1196463600000,0.67850], [1196550000000,0.68180], [1196636400000,0.68360], [1196722800000,0.68230], [1196809200000,0.68050], [1196895600000,0.67930], [1196982000000,0.68490], [1197068400000,0.68330], [1197154800000,0.68250], [1197241200000,0.68250], [1197327600000,0.68160], [1197414000000,0.67990], [1197500400000,0.68130], [1197586800000,0.68090], [1197673200000,0.68680], [1197759600000,0.69330], [1197846000000,0.69330], [1197932400000,0.69450], [1198018800000,0.69440], [1198105200000,0.69460], [1198191600000,0.69640], [1198278000000,0.69650], [1198364400000,0.69560], [1198450800000,0.69560], [1198537200000,0.6950], [1198623600000,0.69480], [1198710000000,0.69280], [1198796400000,0.68870], [1198882800000,0.68240], [1198969200000,0.67940], [1199055600000,0.67940], [1199142000000,0.68030], [1199228400000,0.68550], [1199314800000,0.68240], [1199401200000,0.67910], [1199487600000,0.67830], [1199574000000,0.67850], [1199660400000,0.67850], [1199746800000,0.67970], [1199833200000,0.680], [1199919600000,0.68030], [1200006000000,0.68050], [1200092400000,0.6760], [1200178800000,0.6770], [1200265200000,0.6770], [1200351600000,0.67360], [1200438000000,0.67260], [1200524400000,0.67640], [1200610800000,0.68210], [1200697200000,0.68310], [1200783600000,0.68420], [1200870000000,0.68420], [1200956400000,0.68870], [1201042800000,0.69030], [1201129200000,0.68480], [1201215600000,0.68240], [1201302000000,0.67880], [1201388400000,0.68140], [1201474800000,0.68140], [1201561200000,0.67970], [1201647600000,0.67690], [1201734000000,0.67650], [1201820400000,0.67330], [1201906800000,0.67290], [1201993200000,0.67580], [1202079600000,0.67580], [1202166000000,0.6750], [1202252400000,0.6780], [1202338800000,0.68330], [1202425200000,0.68560], [1202511600000,0.69030], [1202598000000,0.68960], [1202684400000,0.68960], [1202770800000,0.68820], [1202857200000,0.68790], [1202943600000,0.68620], [1203030000000,0.68520], [1203116400000,0.68230], [1203202800000,0.68130], [1203289200000,0.68130], [1203375600000,0.68220], [1203462000000,0.68020], [1203548400000,0.68020], [1203634800000,0.67840], [1203721200000,0.67480], [1203807600000,0.67470], [1203894000000,0.67470], [1203980400000,0.67480], [1204066800000,0.67330], [1204153200000,0.6650], [1204239600000,0.66110], [1204326000000,0.65830], [1204412400000,0.6590], [1204498800000,0.6590], [1204585200000,0.65810], [1204671600000,0.65780], [1204758000000,0.65740], [1204844400000,0.65320], [1204930800000,0.65020], [1205017200000,0.65140], [1205103600000,0.65140], [1205190000000,0.65070], [1205276400000,0.6510], [1205362800000,0.64890], [1205449200000,0.64240], [1205535600000,0.64060], [1205622000000,0.63820], [1205708400000,0.63820], [1205794800000,0.63410], [1205881200000,0.63440], [1205967600000,0.63780], [1206054000000,0.64390], [1206140400000,0.64780], [1206226800000,0.64810], [1206313200000,0.64810], [1206399600000,0.64940], [1206486000000,0.64380], [1206572400000,0.63770], [1206658800000,0.63290], [1206745200000,0.63360], [1206831600000,0.63330], [1206914400000,0.63330], [1207000800000,0.6330], [1207087200000,0.63710], [1207173600000,0.64030], [1207260000000,0.63960], [1207346400000,0.63640], [1207432800000,0.63560], [1207519200000,0.63560], [1207605600000,0.63680], [1207692000000,0.63570], [1207778400000,0.63540], [1207864800000,0.6320], [1207951200000,0.63320], [1208037600000,0.63280], [1208124000000,0.63310], [1208210400000,0.63420], [1208296800000,0.63210], [1208383200000,0.63020], [1208469600000,0.62780], [1208556000000,0.63080], [1208642400000,0.63240], [1208728800000,0.63240], [1208815200000,0.63070], [1208901600000,0.62770], [1208988000000,0.62690], [1209074400000,0.63350], [1209160800000,0.63920], [1209247200000,0.640], [1209333600000,0.64010], [1209420000000,0.63960], [1209506400000,0.64070], [1209592800000,0.64230], [1209679200000,0.64290], [1209765600000,0.64720], [1209852000000,0.64850], [1209938400000,0.64860], [1210024800000,0.64670], [1210111200000,0.64440], [1210197600000,0.64670], [1210284000000,0.65090], [1210370400000,0.64780], [1210456800000,0.64610], [1210543200000,0.64610], [1210629600000,0.64680], [1210716000000,0.64490], [1210802400000,0.6470], [1210888800000,0.64610], [1210975200000,0.64520], [1211061600000,0.64220], [1211148000000,0.64220], [1211234400000,0.64250], [1211320800000,0.64140], [1211407200000,0.63660], [1211493600000,0.63460], [1211580000000,0.6350], [1211666400000,0.63460], [1211752800000,0.63460], [1211839200000,0.63430], [1211925600000,0.63460], [1212012000000,0.63790], [1212098400000,0.64160], [1212184800000,0.64420], [1212271200000,0.64310], [1212357600000,0.64310], [1212444000000,0.64350], [1212530400000,0.6440], [1212616800000,0.64730], [1212703200000,0.64690], [1212789600000,0.63860], [1212876000000,0.63560], [1212962400000,0.6340], [1213048800000,0.63460], [1213135200000,0.6430], [1213221600000,0.64520], [1213308000000,0.64670], [1213394400000,0.65060], [1213480800000,0.65040], [1213567200000,0.65030], [1213653600000,0.64810], [1213740000000,0.64510], [1213826400000,0.6450], [1213912800000,0.64410], [1213999200000,0.64140], [1214085600000,0.64090], [1214172000000,0.64090], [1214258400000,0.64280], [1214344800000,0.64310], [1214431200000,0.64180], [1214517600000,0.63710], [1214604000000,0.63490], [1214690400000,0.63330], [1214776800000,0.63340], [1214863200000,0.63380], [1214949600000,0.63420], [1215036000000,0.6320], [1215122400000,0.63180], [1215208800000,0.6370], [1215295200000,0.63680], [1215381600000,0.63680], [1215468000000,0.63830], [1215554400000,0.63710], [1215640800000,0.63710], [1215727200000,0.63550], [1215813600000,0.6320], [1215900000000,0.62770], [1215986400000,0.62760], [1216072800000,0.62910], [1216159200000,0.62740], [1216245600000,0.62930], [1216332000000,0.63110], [1216418400000,0.6310], [1216504800000,0.63120], [1216591200000,0.63120], [1216677600000,0.63040], [1216764000000,0.62940], [1216850400000,0.63480], [1216936800000,0.63780], [1217023200000,0.63680], [1217109600000,0.63680], [1217196000000,0.63680], [1217282400000,0.6360], [1217368800000,0.6370], [1217455200000,0.64180], [1217541600000,0.64110], [1217628000000,0.64350], [1217714400000,0.64270], [1217800800000,0.64270], [1217887200000,0.64190], [1217973600000,0.64460], [1218060000000,0.64680], [1218146400000,0.64870], [1218232800000,0.65940], [1218319200000,0.66660], [1218405600000,0.66660], [1218492000000,0.66780], [1218578400000,0.67120], [1218664800000,0.67050], [1218751200000,0.67180], [1218837600000,0.67840], [1218924000000,0.68110], [1219010400000,0.68110], [1219096800000,0.67940], [1219183200000,0.68040], [1219269600000,0.67810], [1219356000000,0.67560], [1219442400000,0.67350], [1219528800000,0.67630], [1219615200000,0.67620], [1219701600000,0.67770], [1219788000000,0.68150], [1219874400000,0.68020], [1219960800000,0.6780], [1220047200000,0.67960], [1220133600000,0.68170], [1220220000000,0.68170], [1220306400000,0.68320], [1220392800000,0.68770], [1220479200000,0.69120], [1220565600000,0.69140], [1220652000000,0.70090], [1220738400000,0.70120], [1220824800000,0.7010], [1220911200000,0.70050]]; var exchangerates = [[1167606000000,0.7580], [1167692400000,0.7580], [1167778800000,0.75470], [1167865200000,0.75490], [1167951600000,0.76130], [1168038000000,0.76550], [1168124400000,0.76930], [1168210800000,0.76940], [1168297200000,0.76880], [1168383600000,0.76780], [1168470000000,0.77080], [1168556400000,0.77270], [1168642800000,0.77490], [1168729200000,0.77410], [1168815600000,0.77410], [1168902000000,0.77320], [1168988400000,0.77270], [1169074800000,0.77370], [1169161200000,0.77240], [1169247600000,0.77120], [1169334000000,0.7720], [1169420400000,0.77210], [1169506800000,0.77170], [1169593200000,0.77040], [1169679600000,0.7690], [1169766000000,0.77110], [1169852400000,0.7740], [1169938800000,0.77450], [1170025200000,0.77450], [1170111600000,0.7740], [1170198000000,0.77160], [1170284400000,0.77130], [1170370800000,0.76780], [1170457200000,0.76880], [1170543600000,0.77180], [1170630000000,0.77180], [1170716400000,0.77280], [1170802800000,0.77290], [1170889200000,0.76980], [1170975600000,0.76850], [1171062000000,0.76810], [1171148400000,0.7690], [1171234800000,0.7690], [1171321200000,0.76980], [1171407600000,0.76990], [1171494000000,0.76510], [1171580400000,0.76130], [1171666800000,0.76160], [1171753200000,0.76140], [1171839600000,0.76140], [1171926000000,0.76070], [1172012400000,0.76020], [1172098800000,0.76110], [1172185200000,0.76220], [1172271600000,0.76150], [1172358000000,0.75980], [1172444400000,0.75980], [1172530800000,0.75920], [1172617200000,0.75730], [1172703600000,0.75660], [1172790000000,0.75670], [1172876400000,0.75910], [1172962800000,0.75820], [1173049200000,0.75850], [1173135600000,0.76130], [1173222000000,0.76310], [1173308400000,0.76150], [1173394800000,0.760], [1173481200000,0.76130], [1173567600000,0.76270], [1173654000000,0.76270], [1173740400000,0.76080], [1173826800000,0.75830], [1173913200000,0.75750], [1173999600000,0.75620], [1174086000000,0.7520], [1174172400000,0.75120], [1174258800000,0.75120], [1174345200000,0.75170], [1174431600000,0.7520], [1174518000000,0.75110], [1174604400000,0.7480], [1174690800000,0.75090], [1174777200000,0.75310], [1174860000000,0.75310], [1174946400000,0.75270], [1175032800000,0.74980], [1175119200000,0.74930], [1175205600000,0.75040], [1175292000000,0.750], [1175378400000,0.74910], [1175464800000,0.74910], [1175551200000,0.74850], [1175637600000,0.74840], [1175724000000,0.74920], [1175810400000,0.74710], [1175896800000,0.74590], [1175983200000,0.74770], [1176069600000,0.74770], [1176156000000,0.74830], [1176242400000,0.74580], [1176328800000,0.74480], [1176415200000,0.7430], [1176501600000,0.73990], [1176588000000,0.73950], [1176674400000,0.73950], [1176760800000,0.73780], [1176847200000,0.73820], [1176933600000,0.73620], [1177020000000,0.73550], [1177106400000,0.73480], [1177192800000,0.73610], [1177279200000,0.73610], [1177365600000,0.73650], [1177452000000,0.73620], [1177538400000,0.73310], [1177624800000,0.73390], [1177711200000,0.73440], [1177797600000,0.73270], [1177884000000,0.73270], [1177970400000,0.73360], [1178056800000,0.73330], [1178143200000,0.73590], [1178229600000,0.73590], [1178316000000,0.73720], [1178402400000,0.7360], [1178488800000,0.7360], [1178575200000,0.7350], [1178661600000,0.73650], [1178748000000,0.73840], [1178834400000,0.73950], [1178920800000,0.74130], [1179007200000,0.73970], [1179093600000,0.73960], [1179180000000,0.73850], [1179266400000,0.73780], [1179352800000,0.73660], [1179439200000,0.740], [1179525600000,0.74110], [1179612000000,0.74060], [1179698400000,0.74050], [1179784800000,0.74140], [1179871200000,0.74310], [1179957600000,0.74310], [1180044000000,0.74380], [1180130400000,0.74430], [1180216800000,0.74430], [1180303200000,0.74430], [1180389600000,0.74340], [1180476000000,0.74290], [1180562400000,0.74420], [1180648800000,0.7440], [1180735200000,0.74390], [1180821600000,0.74370], [1180908000000,0.74370], [1180994400000,0.74290], [1181080800000,0.74030], [1181167200000,0.73990], [1181253600000,0.74180], [1181340000000,0.74680], [1181426400000,0.7480], [1181512800000,0.7480], [1181599200000,0.7490], [1181685600000,0.74940], [1181772000000,0.75220], [1181858400000,0.75150], [1181944800000,0.75020], [1182031200000,0.74720], [1182117600000,0.74720], [1182204000000,0.74620], [1182290400000,0.74550], [1182376800000,0.74490], [1182463200000,0.74670], [1182549600000,0.74580], [1182636000000,0.74270], [1182722400000,0.74270], [1182808800000,0.7430], [1182895200000,0.74290], [1182981600000,0.7440], [1183068000000,0.7430], [1183154400000,0.74220], [1183240800000,0.73880], [1183327200000,0.73880], [1183413600000,0.73690], [1183500000000,0.73450], [1183586400000,0.73450], [1183672800000,0.73450], [1183759200000,0.73520], [1183845600000,0.73410], [1183932000000,0.73410], [1184018400000,0.7340], [1184104800000,0.73240], [1184191200000,0.72720], [1184277600000,0.72640], [1184364000000,0.72550], [1184450400000,0.72580], [1184536800000,0.72580], [1184623200000,0.72560], [1184709600000,0.72570], [1184796000000,0.72470], [1184882400000,0.72430], [1184968800000,0.72440], [1185055200000,0.72350], [1185141600000,0.72350], [1185228000000,0.72350], [1185314400000,0.72350], [1185400800000,0.72620], [1185487200000,0.72880], [1185573600000,0.73010], [1185660000000,0.73370], [1185746400000,0.73370], [1185832800000,0.73240], [1185919200000,0.72970], [1186005600000,0.73170], [1186092000000,0.73150], [1186178400000,0.72880], [1186264800000,0.72630], [1186351200000,0.72630], [1186437600000,0.72420], [1186524000000,0.72530], [1186610400000,0.72640], [1186696800000,0.7270], [1186783200000,0.73120], [1186869600000,0.73050], [1186956000000,0.73050], [1187042400000,0.73180], [1187128800000,0.73580], [1187215200000,0.74090], [1187301600000,0.74540], [1187388000000,0.74370], [1187474400000,0.74240], [1187560800000,0.74240], [1187647200000,0.74150], [1187733600000,0.74190], [1187820000000,0.74140], [1187906400000,0.73770], [1187992800000,0.73550], [1188079200000,0.73150], [1188165600000,0.73150], [1188252000000,0.7320], [1188338400000,0.73320], [1188424800000,0.73460], [1188511200000,0.73280], [1188597600000,0.73230], [1188684000000,0.7340], [1188770400000,0.7340], [1188856800000,0.73360], [1188943200000,0.73510], [1189029600000,0.73460], [1189116000000,0.73210], [1189202400000,0.72940], [1189288800000,0.72660], [1189375200000,0.72660], [1189461600000,0.72540], [1189548000000,0.72420], [1189634400000,0.72130], [1189720800000,0.71970], [1189807200000,0.72090], [1189893600000,0.7210], [1189980000000,0.7210], [1190066400000,0.7210], [1190152800000,0.72090], [1190239200000,0.71590], [1190325600000,0.71330], [1190412000000,0.71050], [1190498400000,0.70990], [1190584800000,0.70990], [1190671200000,0.70930], [1190757600000,0.70930], [1190844000000,0.70760], [1190930400000,0.7070], [1191016800000,0.70490], [1191103200000,0.70120], [1191189600000,0.70110], [1191276000000,0.70190], [1191362400000,0.70460], [1191448800000,0.70630], [1191535200000,0.70890], [1191621600000,0.70770], [1191708000000,0.70770], [1191794400000,0.70770], [1191880800000,0.70910], [1191967200000,0.71180], [1192053600000,0.70790], [1192140000000,0.70530], [1192226400000,0.7050], [1192312800000,0.70550], [1192399200000,0.70550], [1192485600000,0.70450], [1192572000000,0.70510], [1192658400000,0.70510], [1192744800000,0.70170], [1192831200000,0.70], [1192917600000,0.69950], [1193004000000,0.69940], [1193090400000,0.70140], [1193176800000,0.70360], [1193263200000,0.70210], [1193349600000,0.70020], [1193436000000,0.69670], [1193522400000,0.6950], [1193612400000,0.6950], [1193698800000,0.69390], [1193785200000,0.6940], [1193871600000,0.69220], [1193958000000,0.69190], [1194044400000,0.69140], [1194130800000,0.68940], [1194217200000,0.68910], [1194303600000,0.69040], [1194390000000,0.6890], [1194476400000,0.68340], [1194562800000,0.68230], [1194649200000,0.68070], [1194735600000,0.68150], [1194822000000,0.68150], [1194908400000,0.68470], [1194994800000,0.68590], [1195081200000,0.68220], [1195167600000,0.68270], [1195254000000,0.68370], [1195340400000,0.68230], [1195426800000,0.68220], [1195513200000,0.68220], [1195599600000,0.67920], [1195686000000,0.67460], [1195772400000,0.67350], [1195858800000,0.67310], [1195945200000,0.67420], [1196031600000,0.67440], [1196118000000,0.67390], [1196204400000,0.67310], [1196290800000,0.67610], [1196377200000,0.67610], [1196463600000,0.67850], [1196550000000,0.68180], [1196636400000,0.68360], [1196722800000,0.68230], [1196809200000,0.68050], [1196895600000,0.67930], [1196982000000,0.68490], [1197068400000,0.68330], [1197154800000,0.68250], [1197241200000,0.68250], [1197327600000,0.68160], [1197414000000,0.67990], [1197500400000,0.68130], [1197586800000,0.68090], [1197673200000,0.68680], [1197759600000,0.69330], [1197846000000,0.69330], [1197932400000,0.69450], [1198018800000,0.69440], [1198105200000,0.69460], [1198191600000,0.69640], [1198278000000,0.69650], [1198364400000,0.69560], [1198450800000,0.69560], [1198537200000,0.6950], [1198623600000,0.69480], [1198710000000,0.69280], [1198796400000,0.68870], [1198882800000,0.68240], [1198969200000,0.67940], [1199055600000,0.67940], [1199142000000,0.68030], [1199228400000,0.68550], [1199314800000,0.68240], [1199401200000,0.67910], [1199487600000,0.67830], [1199574000000,0.67850], [1199660400000,0.67850], [1199746800000,0.67970], [1199833200000,0.680], [1199919600000,0.68030], [1200006000000,0.68050], [1200092400000,0.6760], [1200178800000,0.6770], [1200265200000,0.6770], [1200351600000,0.67360], [1200438000000,0.67260], [1200524400000,0.67640], [1200610800000,0.68210], [1200697200000,0.68310], [1200783600000,0.68420], [1200870000000,0.68420], [1200956400000,0.68870], [1201042800000,0.69030], [1201129200000,0.68480], [1201215600000,0.68240], [1201302000000,0.67880], [1201388400000,0.68140], [1201474800000,0.68140], [1201561200000,0.67970], [1201647600000,0.67690], [1201734000000,0.67650], [1201820400000,0.67330], [1201906800000,0.67290], [1201993200000,0.67580], [1202079600000,0.67580], [1202166000000,0.6750], [1202252400000,0.6780], [1202338800000,0.68330], [1202425200000,0.68560], [1202511600000,0.69030], [1202598000000,0.68960], [1202684400000,0.68960], [1202770800000,0.68820], [1202857200000,0.68790], [1202943600000,0.68620], [1203030000000,0.68520], [1203116400000,0.68230], [1203202800000,0.68130], [1203289200000,0.68130], [1203375600000,0.68220], [1203462000000,0.68020], [1203548400000,0.68020], [1203634800000,0.67840], [1203721200000,0.67480], [1203807600000,0.67470], [1203894000000,0.67470], [1203980400000,0.67480], [1204066800000,0.67330], [1204153200000,0.6650], [1204239600000,0.66110], [1204326000000,0.65830], [1204412400000,0.6590], [1204498800000,0.6590], [1204585200000,0.65810], [1204671600000,0.65780], [1204758000000,0.65740], [1204844400000,0.65320], [1204930800000,0.65020], [1205017200000,0.65140], [1205103600000,0.65140], [1205190000000,0.65070], [1205276400000,0.6510], [1205362800000,0.64890], [1205449200000,0.64240], [1205535600000,0.64060], [1205622000000,0.63820], [1205708400000,0.63820], [1205794800000,0.63410], [1205881200000,0.63440], [1205967600000,0.63780], [1206054000000,0.64390], [1206140400000,0.64780], [1206226800000,0.64810], [1206313200000,0.64810], [1206399600000,0.64940], [1206486000000,0.64380], [1206572400000,0.63770], [1206658800000,0.63290], [1206745200000,0.63360], [1206831600000,0.63330], [1206914400000,0.63330], [1207000800000,0.6330], [1207087200000,0.63710], [1207173600000,0.64030], [1207260000000,0.63960], [1207346400000,0.63640], [1207432800000,0.63560], [1207519200000,0.63560], [1207605600000,0.63680], [1207692000000,0.63570], [1207778400000,0.63540], [1207864800000,0.6320], [1207951200000,0.63320], [1208037600000,0.63280], [1208124000000,0.63310], [1208210400000,0.63420], [1208296800000,0.63210], [1208383200000,0.63020], [1208469600000,0.62780], [1208556000000,0.63080], [1208642400000,0.63240], [1208728800000,0.63240], [1208815200000,0.63070], [1208901600000,0.62770], [1208988000000,0.62690], [1209074400000,0.63350], [1209160800000,0.63920], [1209247200000,0.640], [1209333600000,0.64010], [1209420000000,0.63960], [1209506400000,0.64070], [1209592800000,0.64230], [1209679200000,0.64290], [1209765600000,0.64720], [1209852000000,0.64850], [1209938400000,0.64860], [1210024800000,0.64670], [1210111200000,0.64440], [1210197600000,0.64670], [1210284000000,0.65090], [1210370400000,0.64780], [1210456800000,0.64610], [1210543200000,0.64610], [1210629600000,0.64680], [1210716000000,0.64490], [1210802400000,0.6470], [1210888800000,0.64610], [1210975200000,0.64520], [1211061600000,0.64220], [1211148000000,0.64220], [1211234400000,0.64250], [1211320800000,0.64140], [1211407200000,0.63660], [1211493600000,0.63460], [1211580000000,0.6350], [1211666400000,0.63460], [1211752800000,0.63460], [1211839200000,0.63430], [1211925600000,0.63460], [1212012000000,0.63790], [1212098400000,0.64160], [1212184800000,0.64420], [1212271200000,0.64310], [1212357600000,0.64310], [1212444000000,0.64350], [1212530400000,0.6440], [1212616800000,0.64730], [1212703200000,0.64690], [1212789600000,0.63860], [1212876000000,0.63560], [1212962400000,0.6340], [1213048800000,0.63460], [1213135200000,0.6430], [1213221600000,0.64520], [1213308000000,0.64670], [1213394400000,0.65060], [1213480800000,0.65040], [1213567200000,0.65030], [1213653600000,0.64810], [1213740000000,0.64510], [1213826400000,0.6450], [1213912800000,0.64410], [1213999200000,0.64140], [1214085600000,0.64090], [1214172000000,0.64090], [1214258400000,0.64280], [1214344800000,0.64310], [1214431200000,0.64180], [1214517600000,0.63710], [1214604000000,0.63490], [1214690400000,0.63330], [1214776800000,0.63340], [1214863200000,0.63380], [1214949600000,0.63420], [1215036000000,0.6320], [1215122400000,0.63180], [1215208800000,0.6370], [1215295200000,0.63680], [1215381600000,0.63680], [1215468000000,0.63830], [1215554400000,0.63710], [1215640800000,0.63710], [1215727200000,0.63550], [1215813600000,0.6320], [1215900000000,0.62770], [1215986400000,0.62760], [1216072800000,0.62910], [1216159200000,0.62740], [1216245600000,0.62930], [1216332000000,0.63110], [1216418400000,0.6310], [1216504800000,0.63120], [1216591200000,0.63120], [1216677600000,0.63040], [1216764000000,0.62940], [1216850400000,0.63480], [1216936800000,0.63780], [1217023200000,0.63680], [1217109600000,0.63680], [1217196000000,0.63680], [1217282400000,0.6360], [1217368800000,0.6370], [1217455200000,0.64180], [1217541600000,0.64110], [1217628000000,0.64350], [1217714400000,0.64270], [1217800800000,0.64270], [1217887200000,0.64190], [1217973600000,0.64460], [1218060000000,0.64680], [1218146400000,0.64870], [1218232800000,0.65940], [1218319200000,0.66660], [1218405600000,0.66660], [1218492000000,0.66780], [1218578400000,0.67120], [1218664800000,0.67050], [1218751200000,0.67180], [1218837600000,0.67840], [1218924000000,0.68110], [1219010400000,0.68110], [1219096800000,0.67940], [1219183200000,0.68040], [1219269600000,0.67810], [1219356000000,0.67560], [1219442400000,0.67350], [1219528800000,0.67630], [1219615200000,0.67620], [1219701600000,0.67770], [1219788000000,0.68150], [1219874400000,0.68020], [1219960800000,0.6780], [1220047200000,0.67960], [1220133600000,0.68170], [1220220000000,0.68170], [1220306400000,0.68320], [1220392800000,0.68770], [1220479200000,0.69120], [1220565600000,0.69140], [1220652000000,0.70090], [1220738400000,0.70120], [1220824800000,0.7010], [1220911200000,0.70050]];
function euroFormatter(v, axis) {
return v.toFixed(axis.tickDecimals) +"€";
}
function doPlot(position) {
$.plot($("#placeholder"), $.plot($("#placeholder"),
[ { data: oilprices, label: "Oil price ($)" }, [ { data: oilprices, label: "Oil price ($)" },
{ data: exchangerates, label: "USD/EUR exchange rate", yaxis: 2 }], { data: exchangerates, label: "USD/EUR exchange rate", yaxis: 2 }],
{ {
xaxis: { mode: 'time' }, xaxes: [ { mode: 'time' } ],
yaxis: { min: 0 }, yaxes: [ { min: 0 },
y2axis: { tickFormatter: function (v, axis) { return v.toFixed(axis.tickDecimals) +"€" }}, { position: position, tickFormatter: euroFormatter } ],
legend: { position: 'sw' } }); legend: { position: 'sw' }
});
}
doPlot("right");
$("button").click(function () {
doPlot($(this).text());
});
}); });
</script> </script>
</body> </body>
......
/* /*
Flot plugin for showing a crosshair, thin lines, when the mouse hovers Flot plugin for showing crosshairs, thin lines, when the mouse hovers
over the plot. over the plot.
crosshair: { crosshair: {
...@@ -19,10 +19,11 @@ The plugin also adds four public methods: ...@@ -19,10 +19,11 @@ The plugin also adds four public methods:
- setCrosshair(pos) - setCrosshair(pos)
Set the position of the crosshair. Note that this is cleared if Set the position of the crosshair. Note that this is cleared if
the user moves the mouse. "pos" should be on the form { x: xpos, the user moves the mouse. "pos" is in coordinates of the plot and
y: ypos } (or x2 and y2 if you're using the secondary axes), which should be on the form { x: xpos, y: ypos } (you can use x2/x3/...
is coincidentally the same format as what you get from a "plothover" if you're using multiple axes), which is coincidentally the same
event. If "pos" is null, the crosshair is cleared. format as what you get from a "plothover" event. If "pos" is null,
the crosshair is cleared.
- clearCrosshair() - clearCrosshair()
...@@ -69,10 +70,9 @@ The plugin also adds four public methods: ...@@ -69,10 +70,9 @@ The plugin also adds four public methods:
if (!pos) if (!pos)
crosshair.x = -1; crosshair.x = -1;
else { else {
var axes = plot.getAxes(); var o = plot.p2c(pos);
crosshair.x = Math.max(0, Math.min(o.left, plot.width()));
crosshair.x = Math.max(0, Math.min(pos.x != null ? axes.xaxis.p2c(pos.x) : axes.x2axis.p2c(pos.x2), plot.width())); crosshair.y = Math.max(0, Math.min(o.top, plot.height()));
crosshair.y = Math.max(0, Math.min(pos.y != null ? axes.yaxis.p2c(pos.y) : axes.y2axis.p2c(pos.y2), plot.height()));
} }
plot.triggerRedrawOverlay(); plot.triggerRedrawOverlay();
......
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
backgroundOpacity: 0.85 // set to 0 to avoid background backgroundOpacity: 0.85 // set to 0 to avoid background
}, },
xaxis: { xaxis: {
position: "bottom", // or "top"
mode: null, // null or "time" mode: null, // null or "time"
transform: null, // null or f: number -> number to transform axis transform: null, // null or f: number -> number to transform axis
inverseTransform: null, // if transform is set, this should be the inverse function inverseTransform: null, // if transform is set, this should be the inverse function
...@@ -59,6 +60,7 @@ ...@@ -59,6 +60,7 @@
autoscaleMargin: null, // margin in % to add if auto-setting min/max autoscaleMargin: null, // margin in % to add if auto-setting min/max
ticks: null, // either [1, 3] or [[1, "a"], 3] or (fn: axis info -> ticks) or app. number of ticks for auto-ticks ticks: null, // either [1, 3] or [[1, "a"], 3] or (fn: axis info -> ticks) or app. number of ticks for auto-ticks
tickFormatter: null, // fn: number -> string tickFormatter: null, // fn: number -> string
tickLength: null, // size in pixels of ticks, or "full" for whole line
labelWidth: null, // size of tick labels in pixels labelWidth: null, // size of tick labels in pixels
labelHeight: null, labelHeight: null,
...@@ -71,14 +73,11 @@ ...@@ -71,14 +73,11 @@
twelveHourClock: false // 12 or 24 time in time mode twelveHourClock: false // 12 or 24 time in time mode
}, },
yaxis: { yaxis: {
autoscaleMargin: 0.02 autoscaleMargin: 0.02,
}, position: "left" // or "right"
x2axis: {
autoscaleMargin: null
},
y2axis: {
autoscaleMargin: 0.02
}, },
xaxes: [],
yaxes: [],
series: { series: {
points: { points: {
show: false, show: false,
...@@ -113,6 +112,7 @@ ...@@ -113,6 +112,7 @@
backgroundColor: null, // null for transparent, else color backgroundColor: null, // null for transparent, else color
tickColor: "rgba(0,0,0,0.15)", // color used for the ticks tickColor: "rgba(0,0,0,0.15)", // color used for the ticks
labelMargin: 5, // in pixels labelMargin: 5, // in pixels
axisMargin: 8, // in pixels
borderWidth: 2, // in pixels borderWidth: 2, // in pixels
borderColor: null, // set if different from the grid color borderColor: null, // set if different from the grid color
markings: null, // array of ranges or fn: axes -> array of ranges markings: null, // array of ranges or fn: axes -> array of ranges
...@@ -130,8 +130,9 @@ ...@@ -130,8 +130,9 @@
overlay = null, // canvas for interactive stuff on top of plot overlay = null, // canvas for interactive stuff on top of plot
eventHolder = null, // jQuery object that events should be bound to eventHolder = null, // jQuery object that events should be bound to
ctx = null, octx = null, ctx = null, octx = null,
axes = { xaxis: { n: 1 }, yaxis: { n: 1 }, /*axes = { xaxis: { n: 1 }, yaxis: { n: 1 },
x2axis: { n: 2 }, y2axis: { n: 2 } }, x2axis: { n: 2 }, y2axis: { n: 2 } },*/
xaxes = [], yaxes = [],
plotOffset = { left: 0, right: 0, top: 0, bottom: 0}, plotOffset = { left: 0, right: 0, top: 0, bottom: 0},
canvasWidth = 0, canvasHeight = 0, canvasWidth = 0, canvasHeight = 0,
plotWidth = 0, plotHeight = 0, plotWidth = 0, plotHeight = 0,
...@@ -161,17 +162,43 @@ ...@@ -161,17 +162,43 @@
o.top += plotOffset.top; o.top += plotOffset.top;
return o; return o;
}; };
plot.getData = function() { return series; }; plot.getData = function () { return series; };
plot.getAxes = function() { return axes; }; plot.getAxis = function (dir, number) {
plot.getOptions = function() { return options; }; var a = (dir == x ? xaxes : yaxes)[number - 1];
if (a && !a.used)
a = null;
return a;
};
plot.getAxes = function () {
var res = {}, i;
for (i = 0; i < xaxes.length; ++i)
res["x" + (i ? (i + 1) : "") + "axis"] = xaxes[i] || {};
for (i = 0; i < yaxes.length; ++i)
res["y" + (i ? (i + 1) : "") + "axis"] = yaxes[i] || {};
// backwards compatibility - to be removed
if (!res.x2axis)
res.x2axis = { n: 2 };
if (!res.y2axis)
res.y2axis = { n: 2 };
return res;
};
plot.getXAxes = function () { return xaxes; };
plot.getYAxes = function () { return yaxes; };
plot.getUsedAxes = getUsedAxes; // return flat array with x and y axes that are in use
plot.c2p = canvasToAxisCoords;
plot.p2c = axisToCanvasCoords;
plot.getOptions = function () { return options; };
plot.highlight = highlight; plot.highlight = highlight;
plot.unhighlight = unhighlight; plot.unhighlight = unhighlight;
plot.triggerRedrawOverlay = triggerRedrawOverlay; plot.triggerRedrawOverlay = triggerRedrawOverlay;
plot.pointOffset = function(point) { plot.pointOffset = function(point) {
return { left: parseInt(axisSpecToRealAxis(point, "xaxis").p2c(+point.x) + plotOffset.left), return {
top: parseInt(axisSpecToRealAxis(point, "yaxis").p2c(+point.y) + plotOffset.top) }; left: parseInt(xaxes[axisNumber(point, "x") - 1].p2c(+point.x) + plotOffset.left),
top: parseInt(yaxes[axisNumber(point, "y") - 1].p2c(+point.y) + plotOffset.top)
};
}; };
// public attributes // public attributes
plot.hooks = hooks; plot.hooks = hooks;
...@@ -202,14 +229,33 @@ ...@@ -202,14 +229,33 @@
} }
function parseOptions(opts) { function parseOptions(opts) {
var i;
$.extend(true, options, opts); $.extend(true, options, opts);
if (options.grid.borderColor == null) if (options.grid.borderColor == null)
options.grid.borderColor = options.grid.color; options.grid.borderColor = options.grid.color;
// fill in defaults in axes, copy at least always the
// first as the rest of the code assumes it'll be there
for (i = 0; i < Math.max(1, options.xaxes.length); ++i)
options.xaxes[i] = $.extend(true, {}, options.xaxis, options.xaxes[i]);
for (i = 0; i < Math.max(1, options.yaxes.length); ++i)
options.yaxes[i] = $.extend(true, {}, options.yaxis, options.yaxes[i]);
// backwards compatibility, to be removed in future // backwards compatibility, to be removed in future
if (options.xaxis.noTicks && options.xaxis.ticks == null) if (options.xaxis.noTicks && options.xaxis.ticks == null)
options.xaxis.ticks = options.xaxis.noTicks; options.xaxis.ticks = options.xaxis.noTicks;
if (options.yaxis.noTicks && options.yaxis.ticks == null) if (options.yaxis.noTicks && options.yaxis.ticks == null)
options.yaxis.ticks = options.yaxis.noTicks; options.yaxis.ticks = options.yaxis.noTicks;
if (options.x2axis) {
options.y2axis.position = "top";
options.xaxes[1] = options.x2axis;
}
if (options.y2axis) {
if (options.y2axis.autoscaleMargin === undefined)
options.y2axis.autoscaleMargin = 0.02;
options.y2axis.position = "right";
options.yaxes[1] = options.y2axis;
}
if (options.grid.coloredAreas) if (options.grid.coloredAreas)
options.grid.markings = options.grid.coloredAreas; options.grid.markings = options.grid.coloredAreas;
if (options.grid.coloredAreasColor) if (options.grid.coloredAreasColor)
...@@ -223,6 +269,11 @@ ...@@ -223,6 +269,11 @@
if (options.shadowSize) if (options.shadowSize)
options.series.shadowSize = options.shadowSize; options.series.shadowSize = options.shadowSize;
for (i = 0; i < options.xaxes.length; ++i)
getOrCreateAxis(xaxes, i + 1).options = options.xaxes[i];
for (i = 0; i < options.yaxes.length; ++i)
getOrCreateAxis(yaxes, i + 1).options = options.yaxes[i];
// add hooks from options // add hooks from options
for (var n in hooks) for (var n in hooks)
if (options.hooks[n] && options.hooks[n].length) if (options.hooks[n] && options.hooks[n].length)
...@@ -258,15 +309,97 @@ ...@@ -258,15 +309,97 @@
return res; return res;
} }
function axisSpecToRealAxis(obj, attr) { function axisNumber(obj, coord) {
var a = obj[attr]; var a = obj[coord + "axis"];
if (typeof a == "object") // if we got a real axis, extract number if (typeof a == "object") // if we got a real axis, extract number
a = a.n; a = a.n;
if (typeof a == "number" && a != 1) if (typeof a != "number")
return axes[attr.charAt(0) + a + attr.slice(1)]; a = 1; // default to first axis
return a;
}
function canvasToAxisCoords(pos) {
// return an object with x/y corresponding to all used axes
var res = {}, i, axis;
for (i = 0; i < xaxes.length; ++i) {
axis = xaxes[i];
if (axis && axis.used)
res["x" + axis.n] = axis.c2p(pos.left);
}
for (i = 0; i < yaxes.length; ++i) {
axis = yaxes[i];
if (axis && axis.used)
res["y" + axis.n] = axis.c2p(pos.top);
}
if (res.x1 !== undefined)
res.x = res.x1;
if (res.y1 !== undefined)
res.y = res.y1;
return res;
}
function axisToCanvasCoords(pos) {
// get canvas coords from the first pair of x/y found in pos
var res = {}, i, axis, key;
for (i = 0; i < xaxes.length; ++i) {
axis = xaxes[i];
if (axis && axis.used) {
key = "x" + axis.n;
if (pos[key] == null && axis.n == 1)
key = "x";
if (pos[key]) {
res.left = axis.p2c(pos[key]);
break;
}
}
}
for (i = 0; i < yaxes.length; ++i) {
axis = yaxes[i];
if (axis && axis.used) {
key = "y" + axis.n;
if (pos[key] == null && axis.n == 1)
key = "y";
if (pos[key]) {
res.top = axis.p2c(pos[key]);
break;
}
}
}
return res;
}
function getUsedAxes() {
var res = [], i, axis;
for (i = 0; i < xaxes.length; ++i) {
axis = xaxes[i];
if (axis && axis.used)
res.push(axis);
}
for (i = 0; i < yaxes.length; ++i) {
axis = yaxes[i];
if (axis && axis.used)
res.push(axis);
}
return res;
}
function getOrCreateAxis(axes, number) {
if (!axes[number - 1])
axes[number - 1] = {
n: number, // save the number for future reference
direction: axes == xaxes ? "x" : "y",
options: $.extend(true, {}, axes == xaxes ? options.xaxis : options.yaxis)
};
// default to first axis return axes[number - 1];
return axes[attr];
} }
function fillInSeriesOptions() { function fillInSeriesOptions() {
...@@ -344,8 +477,8 @@ ...@@ -344,8 +477,8 @@
} }
// setup axes // setup axes
s.xaxis = axisSpecToRealAxis(s, "xaxis"); s.xaxis = getOrCreateAxis(xaxes, axisNumber(s, "x"));
s.yaxis = axisSpecToRealAxis(s, "yaxis"); s.yaxis = getOrCreateAxis(yaxes, axisNumber(s, "y"));
} }
} }
...@@ -355,10 +488,13 @@ ...@@ -355,10 +488,13 @@
i, j, k, m, length, i, j, k, m, length,
s, points, ps, x, y, axis, val, f, p; s, points, ps, x, y, axis, val, f, p;
for (axis in axes) { function initAxis(axis, number) {
axes[axis].datamin = topSentry; if (!axis)
axes[axis].datamax = bottomSentry; return;
axes[axis].used = false;
axis.datamin = topSentry;
axis.datamax = bottomSentry;
axis.used = false;
} }
function updateAxis(axis, min, max) { function updateAxis(axis, min, max) {
...@@ -368,6 +504,11 @@ ...@@ -368,6 +504,11 @@
axis.datamax = max; axis.datamax = max;
} }
for (i = 0; i < xaxes.length; ++i)
initAxis(xaxes[i]);
for (i = 0; i < yaxes.length; ++i)
initAxis(yaxes[i]);
for (i = 0; i < series.length; ++i) { for (i = 0; i < series.length; ++i) {
s = series[i]; s = series[i];
s.datapoints = { points: [] }; s.datapoints = { points: [] };
...@@ -533,12 +674,12 @@ ...@@ -533,12 +674,12 @@
updateAxis(s.yaxis, ymin, ymax); updateAxis(s.yaxis, ymin, ymax);
} }
for (axis in axes) { $.each(getUsedAxes(), function (i, axis) {
if (axes[axis].datamin == topSentry) if (axis.datamin == topSentry)
axes[axis].datamin = null; axis.datamin = null;
if (axes[axis].datamax == bottomSentry) if (axis.datamax == bottomSentry)
axes[axis].datamax = null; axis.datamax = null;
} });
} }
function constructCanvas() { function constructCanvas() {
...@@ -588,15 +729,16 @@ ...@@ -588,15 +729,16 @@
executeHooks(hooks.bindEvents, [eventHolder]); executeHooks(hooks.bindEvents, [eventHolder]);
} }
function setupGrid() { function setTransformationHelpers(axis) {
function setTransformationHelpers(axis, o) { // set helper functions on the axis, assumes plot area
// has been computed already
function identity(x) { return x; } function identity(x) { return x; }
var s, m, t = o.transform || identity, var s, m, t = axis.options.transform || identity,
it = o.inverseTransform; it = axis.options.inverseTransform;
// add transformation helpers if (axis.direction == "x") {
if (axis == axes.xaxis || axis == axes.x2axis) {
// precompute how much the axis is scaling a point // precompute how much the axis is scaling a point
// in canvas space // in canvas space
s = axis.scale = plotWidth / (t(axis.max) - t(axis.min)); s = axis.scale = plotWidth / (t(axis.max) - t(axis.min));
...@@ -628,143 +770,242 @@ ...@@ -628,143 +770,242 @@
} }
} }
function measureLabels(axis, axisOptions) { function measureTickLabels(axis) {
var i, labels = [], l; if (!axis)
return;
var opts = axis.options, i, ticks = axis.ticks || [], labels = [],
l, w = opts.labelWidth, h = opts.labelHeight, dummyDiv;
axis.labelWidth = axisOptions.labelWidth; function makeDummyDiv(labels, width) {
axis.labelHeight = axisOptions.labelHeight; return $('<div style="position:absolute;top:-10000px;' + width + 'font-size:smaller">' +
'<div class="' + axis.direction + 'Axis ' + axis.direction + axis.n + 'Axis">'
+ labels.join("") + '</div></div>')
.appendTo(placeholder);
}
if (axis == axes.xaxis || axis == axes.x2axis) { if (axis.direction == "x") {
// to avoid measuring the widths of the labels, we // to avoid measuring the widths of the labels (it's slow), we
// construct fixed-size boxes and put the labels inside // construct fixed-size boxes and put the labels inside
// them, we don't need the exact figures and the // them, we don't need the exact figures and the
// fixed-size box content is easy to center // fixed-size box content is easy to center
if (axis.labelWidth == null) if (w == null)
axis.labelWidth = canvasWidth / (axis.ticks.length > 0 ? axis.ticks.length : 1); w = canvasWidth / (ticks.length > 0 ? ticks.length : 1);
// measure x label heights // measure x label heights
if (axis.labelHeight == null) { if (h == null) {
labels = []; labels = [];
for (i = 0; i < axis.ticks.length; ++i) { for (i = 0; i < ticks.length; ++i) {
l = axis.ticks[i].label; l = ticks[i].label;
if (l) if (l)
labels.push('<div class="tickLabel" style="float:left;width:' + axis.labelWidth + 'px">' + l + '</div>'); labels.push('<div class="tickLabel" style="float:left;width:' + w + 'px">' + l + '</div>');
} }
if (labels.length > 0) { if (labels.length > 0) {
var dummyDiv = $('<div style="position:absolute;top:-10000px;width:10000px;font-size:smaller">' // stick them all in the same div and measure
+ labels.join("") + '<div style="clear:left"></div></div>').appendTo(placeholder); // collective height
axis.labelHeight = dummyDiv.height(); labels.push('<div style="clear:left"></div>');
dummyDiv = makeDummyDiv(labels, "width:10000px;");
h = dummyDiv.height();
dummyDiv.remove(); dummyDiv.remove();
} }
} }
} }
else if (axis.labelWidth == null || axis.labelHeight == null) { else if (w == null || h == null) {
// calculate y label dimensions // calculate y label dimensions
for (i = 0; i < axis.ticks.length; ++i) { for (i = 0; i < ticks.length; ++i) {
l = axis.ticks[i].label; l = ticks[i].label;
if (l) if (l)
labels.push('<div class="tickLabel">' + l + '</div>'); labels.push('<div class="tickLabel">' + l + '</div>');
} }
if (labels.length > 0) { if (labels.length > 0) {
var dummyDiv = $('<div style="position:absolute;top:-10000px;font-size:smaller">' dummyDiv = makeDummyDiv(labels, "");
+ labels.join("") + '</div>').appendTo(placeholder); if (w == null)
if (axis.labelWidth == null) w = dummyDiv.children().width();
axis.labelWidth = dummyDiv.width(); if (h == null)
if (axis.labelHeight == null) h = dummyDiv.find("div.tickLabel").height();
axis.labelHeight = dummyDiv.find("div").height();
dummyDiv.remove();
} }
} }
if (axis.labelWidth == null) if (w == null)
axis.labelWidth = 0; w = 0;
if (axis.labelHeight == null) if (h == null)
axis.labelHeight = 0; h = 0;
axis.labelWidth = w;
axis.labelHeight = h;
} }
function setGridSpacing() { function computeAxisBox(axis) {
// get the most space needed around the grid for things if (!axis || (!axis.used && !(axis.labelWidth || axis.labelHeight)))
// that may stick out return;
var maxOutset = options.grid.borderWidth;
for (var i = 0; i < series.length; ++i)
maxOutset = Math.max(maxOutset, 2 * (series[i].points.radius + series[i].points.lineWidth/2));
plotOffset.left = plotOffset.right = plotOffset.top = plotOffset.bottom = maxOutset; // find the bounding box of the axis by looking at label
// widths/heights and ticks, make room by diminishing the
// plotOffset
var lw = axis.labelWidth,
lh = axis.labelHeight,
pos = axis.options.position,
tickLength = axis.options.tickLength,
axismargin = options.grid.axisMargin,
padding = options.grid.labelMargin,
all = axis.direction == "x" ? xaxes : yaxes,
index;
// determine axis margin
var samePosition = $.grep(all, function (a) {
return a && a.options.position == pos && (a.labelHeight || a.labelWidth);
});
if ($.inArray(axis, samePosition) == samePosition.length - 1)
axismargin = 0; // outermost
var margin = options.grid.labelMargin + options.grid.borderWidth; // determine tick length - if we're innermost, we can use "full"
if (tickLength == null)
tickLength = "full";
if (axes.xaxis.labelHeight > 0) var sameDirection = $.grep(all, function (a) {
plotOffset.bottom = Math.max(maxOutset, axes.xaxis.labelHeight + margin); return a && (a.labelHeight || a.labelWidth);
if (axes.yaxis.labelWidth > 0) });
plotOffset.left = Math.max(maxOutset, axes.yaxis.labelWidth + margin);
if (axes.x2axis.labelHeight > 0)
plotOffset.top = Math.max(maxOutset, axes.x2axis.labelHeight + margin);
if (axes.y2axis.labelWidth > 0)
plotOffset.right = Math.max(maxOutset, axes.y2axis.labelWidth + margin);
plotWidth = canvasWidth - plotOffset.left - plotOffset.right; if ($.inArray(axis, sameDirection) != 0 && tickLength == "full")
plotHeight = canvasHeight - plotOffset.bottom - plotOffset.top; tickLength = 5;
if (!isNaN(+tickLength))
padding += +tickLength;
// compute box
if (axis.direction == "x") {
lh += padding;
if (pos == "bottom") {
plotOffset.bottom += lh + axismargin;
axis.box = { top: canvasHeight - plotOffset.bottom, height: lh };
}
else {
axis.box = { top: plotOffset.top + axismargin, height: lh };
plotOffset.top += lh + axismargin;
}
} }
else {
lw += padding;
var axis; if (pos == "left") {
for (axis in axes) axis.box = { left: plotOffset.left + axismargin, width: lw };
setRange(axes[axis], options[axis]); plotOffset.left += lw + axismargin;
}
else {
plotOffset.right += lw + axismargin;
axis.box = { left: canvasWidth - plotOffset.right, width: lw };
}
}
if (options.grid.show) { // save for future reference
for (axis in axes) { axis.position = pos;
prepareTickGeneration(axes[axis], options[axis]); axis.tickLength = tickLength;
setTicks(axes[axis], options[axis]); axis.box.padding = padding;
measureLabels(axes[axis], options[axis]); axis.innermost = $.inArray(axis, samePosition) == 0;
} }
setGridSpacing(); function fixupAxisBox(axis) {
// set remaining bounding box coordinates
if (axis.direction == "x") {
axis.box.left = plotOffset.left;
axis.box.width = plotWidth;
} }
else { else {
axis.box.top = plotOffset.top;
axis.box.height = plotHeight;
}
}
function setupGrid() {
var axes = getUsedAxes(), j, k;
// compute axis intervals
for (k = 0; k < axes.length; ++k)
setRange(axes[k]);
plotOffset.left = plotOffset.right = plotOffset.top = plotOffset.bottom = 0; plotOffset.left = plotOffset.right = plotOffset.top = plotOffset.bottom = 0;
plotWidth = canvasWidth; if (options.grid.show) {
plotHeight = canvasHeight; // make the ticks
for (k = 0; k < axes.length; ++k) {
setupTickGeneration(axes[k]);
setTicks(axes[k]);
}
// find labelWidth/Height, do this on all, not just
// used as we might need to reserve space for unused
// to if their labelWidth/Height is set
for (j = 0; j < xaxes.length; ++j)
measureTickLabels(xaxes[j]);
for (j = 0; j < yaxes.length; ++j)
measureTickLabels(yaxes[j]);
// compute the axis boxes, start from the outside (reverse order)
for (j = xaxes.length - 1; j >= 0; --j)
computeAxisBox(xaxes[j]);
for (j = yaxes.length - 1; j >= 0; --j)
computeAxisBox(yaxes[j]);
// make sure we've got enough space for things that
// might stick out
var maxOutset = options.grid.borderWidth;
for (var i = 0; i < series.length; ++i)
maxOutset = Math.max(maxOutset, 2 * (series[i].points.radius + series[i].points.lineWidth/2));
for (var a in plotOffset)
plotOffset[a] = Math.max(maxOutset, plotOffset[a]);
} }
for (axis in axes) plotWidth = canvasWidth - plotOffset.left - plotOffset.right;
setTransformationHelpers(axes[axis], options[axis]); plotHeight = canvasHeight - plotOffset.bottom - plotOffset.top;
// now we got the proper plotWidth/Height, we can compute the scaling
for (k = 0; k < axes.length; ++k)
setTransformationHelpers(axes[k]);
if (options.grid.show) {
for (k = 0; k < axes.length; ++k)
fixupAxisBox(axes[k]);
if (options.grid.show) insertAxisLabels();
insertLabels(); }
insertLegend(); insertLegend();
} }
function setRange(axis, axisOptions) { function setRange(axis) {
var min = +(axisOptions.min != null ? axisOptions.min : axis.datamin), var opts = axis.options,
max = +(axisOptions.max != null ? axisOptions.max : axis.datamax), min = +(opts.min != null ? opts.min : axis.datamin),
max = +(opts.max != null ? opts.max : axis.datamax),
delta = max - min; delta = max - min;
if (delta == 0.0) { if (delta == 0.0) {
// degenerate case // degenerate case
var widen = max == 0 ? 1 : 0.01; var widen = max == 0 ? 1 : 0.01;
if (axisOptions.min == null) if (opts.min == null)
min -= widen; min -= widen;
// alway widen max if we couldn't widen min to ensure we // alway widen max if we couldn't widen min to ensure we
// don't fall into min == max which doesn't work // don't fall into min == max which doesn't work
if (axisOptions.max == null || axisOptions.min != null) if (opts.max == null || opts.min != null)
max += widen; max += widen;
} }
else { else {
// consider autoscaling // consider autoscaling
var margin = axisOptions.autoscaleMargin; var margin = opts.autoscaleMargin;
if (margin != null) { if (margin != null) {
if (axisOptions.min == null) { if (opts.min == null) {
min -= delta * margin; min -= delta * margin;
// make sure we don't go below zero if all values // make sure we don't go below zero if all values
// are positive // are positive
if (min < 0 && axis.datamin != null && axis.datamin >= 0) if (min < 0 && axis.datamin != null && axis.datamin >= 0)
min = 0; min = 0;
} }
if (axisOptions.max == null) { if (opts.max == null) {
max += delta * margin; max += delta * margin;
if (max > 0 && axis.datamax != null && axis.datamax <= 0) if (max > 0 && axis.datamax != null && axis.datamax <= 0)
max = 0; max = 0;
...@@ -775,12 +1016,14 @@ ...@@ -775,12 +1016,14 @@
axis.max = max; axis.max = max;
} }
function prepareTickGeneration(axis, axisOptions) { function setupTickGeneration(axis) {
var opts = axis.options;
// estimate number of ticks // estimate number of ticks
var noTicks; var noTicks;
if (typeof axisOptions.ticks == "number" && axisOptions.ticks > 0) if (typeof opts.ticks == "number" && opts.ticks > 0)
noTicks = axisOptions.ticks; noTicks = opts.ticks;
else if (axis == axes.xaxis || axis == axes.x2axis) else if (axis.direction == "x")
// heuristic based on the model a*sqrt(x) fitted to // heuristic based on the model a*sqrt(x) fitted to
// some reasonable data points // some reasonable data points
noTicks = 0.3 * Math.sqrt(canvasWidth); noTicks = 0.3 * Math.sqrt(canvasWidth);
...@@ -790,7 +1033,7 @@ ...@@ -790,7 +1033,7 @@
var delta = (axis.max - axis.min) / noTicks, var delta = (axis.max - axis.min) / noTicks,
size, generator, unit, formatter, i, magn, norm; size, generator, unit, formatter, i, magn, norm;
if (axisOptions.mode == "time") { if (opts.mode == "time") {
// pretty handling of time // pretty handling of time
// map of app. size of time units in milliseconds // map of app. size of time units in milliseconds
...@@ -820,11 +1063,11 @@ ...@@ -820,11 +1063,11 @@
]; ];
var minSize = 0; var minSize = 0;
if (axisOptions.minTickSize != null) { if (opts.minTickSize != null) {
if (typeof axisOptions.tickSize == "number") if (typeof opts.tickSize == "number")
minSize = axisOptions.tickSize; minSize = opts.tickSize;
else else
minSize = axisOptions.minTickSize[0] * timeUnitSize[axisOptions.minTickSize[1]]; minSize = opts.minTickSize[0] * timeUnitSize[opts.minTickSize[1]];
} }
for (var i = 0; i < spec.length - 1; ++i) for (var i = 0; i < spec.length - 1; ++i)
...@@ -851,9 +1094,9 @@ ...@@ -851,9 +1094,9 @@
size *= magn; size *= magn;
} }
if (axisOptions.tickSize) { if (opts.tickSize) {
size = axisOptions.tickSize[0]; size = opts.tickSize[0];
unit = axisOptions.tickSize[1]; unit = opts.tickSize[1];
} }
generator = function(axis) { generator = function(axis) {
...@@ -923,12 +1166,12 @@ ...@@ -923,12 +1166,12 @@
var d = new Date(v); var d = new Date(v);
// first check global format // first check global format
if (axisOptions.timeformat != null) if (opts.timeformat != null)
return $.plot.formatDate(d, axisOptions.timeformat, axisOptions.monthNames); return $.plot.formatDate(d, opts.timeformat, opts.monthNames);
var t = axis.tickSize[0] * timeUnitSize[axis.tickSize[1]]; var t = axis.tickSize[0] * timeUnitSize[axis.tickSize[1]];
var span = axis.max - axis.min; var span = axis.max - axis.min;
var suffix = (axisOptions.twelveHourClock) ? " %p" : ""; var suffix = (opts.twelveHourClock) ? " %p" : "";
if (t < timeUnitSize.minute) if (t < timeUnitSize.minute)
fmt = "%h:%M:%S" + suffix; fmt = "%h:%M:%S" + suffix;
...@@ -949,12 +1192,12 @@ ...@@ -949,12 +1192,12 @@
else else
fmt = "%y"; fmt = "%y";
return $.plot.formatDate(d, fmt, axisOptions.monthNames); return $.plot.formatDate(d, fmt, opts.monthNames);
}; };
} }
else { else {
// pretty rounding of base-10 numbers // pretty rounding of base-10 numbers
var maxDec = axisOptions.tickDecimals; var maxDec = opts.tickDecimals;
var dec = -Math.floor(Math.log(delta) / Math.LN10); var dec = -Math.floor(Math.log(delta) / Math.LN10);
if (maxDec != null && dec > maxDec) if (maxDec != null && dec > maxDec)
dec = maxDec; dec = maxDec;
...@@ -979,11 +1222,11 @@ ...@@ -979,11 +1222,11 @@
size *= magn; size *= magn;
if (axisOptions.minTickSize != null && size < axisOptions.minTickSize) if (opts.minTickSize != null && size < opts.minTickSize)
size = axisOptions.minTickSize; size = opts.minTickSize;
if (axisOptions.tickSize != null) if (opts.tickSize != null)
size = axisOptions.tickSize; size = opts.tickSize;
axis.tickDecimals = Math.max(0, (maxDec != null) ? maxDec : dec); axis.tickDecimals = Math.max(0, (maxDec != null) ? maxDec : dec);
...@@ -1009,26 +1252,25 @@ ...@@ -1009,26 +1252,25 @@
axis.tickSize = unit ? [size, unit] : size; axis.tickSize = unit ? [size, unit] : size;
axis.tickGenerator = generator; axis.tickGenerator = generator;
if ($.isFunction(axisOptions.tickFormatter)) if ($.isFunction(opts.tickFormatter))
axis.tickFormatter = function (v, axis) { return "" + axisOptions.tickFormatter(v, axis); }; axis.tickFormatter = function (v, axis) { return "" + opts.tickFormatter(v, axis); };
else else
axis.tickFormatter = formatter; axis.tickFormatter = formatter;
} }
function setTicks(axis, axisOptions) { function setTicks(axis) {
axis.ticks = []; var opts = axis.options;
if (!axis.used) axis.ticks = [];
return;
if (axisOptions.ticks == null) if (opts.ticks == null)
axis.ticks = axis.tickGenerator(axis); axis.ticks = axis.tickGenerator(axis);
else if (typeof axisOptions.ticks == "number") { else if (typeof opts.ticks == "number") {
if (axisOptions.ticks > 0) if (opts.ticks > 0)
axis.ticks = axis.tickGenerator(axis); axis.ticks = axis.tickGenerator(axis);
} }
else if (axisOptions.ticks) { else if (opts.ticks) {
var ticks = axisOptions.ticks; var ticks = opts.ticks;
if ($.isFunction(ticks)) if ($.isFunction(ticks))
// generate the ticks // generate the ticks
...@@ -1052,11 +1294,11 @@ ...@@ -1052,11 +1294,11 @@
} }
} }
if (axisOptions.autoscaleMargin != null && axis.ticks.length > 0) { if (opts.autoscaleMargin != null && axis.ticks.length > 0) {
// snap to ticks // snap to ticks
if (axisOptions.min == null) if (opts.min == null)
axis.min = Math.min(axis.min, axis.ticks[0].v); axis.min = Math.min(axis.min, axis.ticks[0].v);
if (axisOptions.max == null && axis.ticks.length > 1) if (opts.max == null && axis.ticks.length > 1)
axis.max = Math.max(axis.max, axis.ticks[axis.ticks.length - 1].v); axis.max = Math.max(axis.max, axis.ticks[axis.ticks.length - 1].v);
} }
} }
...@@ -1081,30 +1323,36 @@ ...@@ -1081,30 +1323,36 @@
} }
function extractRange(ranges, coord) { function extractRange(ranges, coord) {
var firstAxis = coord + "axis", var axis, from, to, axes, key;
secondaryAxis = coord + "2axis",
axis, from, to, reverse; axes = getUsedAxes();
for (i = 0; i < axes.length; ++i) {
if (ranges[firstAxis]) { axis = axes[i];
axis = axes[firstAxis]; if (axis.direction == coord) {
from = ranges[firstAxis].from; key = coord + axis.n + "axis";
to = ranges[firstAxis].to; if (!ranges[key] && axis.n == 1)
key = coord + "axis"; // support x1axis as xaxis
if (ranges[key]) {
from = ranges[key].from;
to = ranges[key].to;
break;
} }
else if (ranges[secondaryAxis]) {
axis = axes[secondaryAxis];
from = ranges[secondaryAxis].from;
to = ranges[secondaryAxis].to;
} }
else { }
// backwards-compat stuff - to be removed in future // backwards-compat stuff - to be removed in future
axis = axes[firstAxis]; if (!ranges[key]) {
axis = coord == "x" ? xaxes[0] : yaxes[0];
from = ranges[coord + "1"]; from = ranges[coord + "1"];
to = ranges[coord + "2"]; to = ranges[coord + "2"];
} }
// auto-reverse as an added bonus // auto-reverse as an added bonus
if (from != null && to != null && from > to) if (from != null && to != null && from > to) {
return { from: to, to: from, axis: axis }; var tmp = from;
from = to;
to = tmp;
}
return { from: from, to: to, axis: axis }; return { from: from, to: to, axis: axis };
} }
...@@ -1124,9 +1372,17 @@ ...@@ -1124,9 +1372,17 @@
// draw markings // draw markings
var markings = options.grid.markings; var markings = options.grid.markings;
if (markings) { if (markings) {
if ($.isFunction(markings)) if ($.isFunction(markings)) {
// xmin etc. are backwards-compatible, to be removed in future var axes = plot.getAxes();
markings = markings({ xmin: axes.xaxis.min, xmax: axes.xaxis.max, ymin: axes.yaxis.min, ymax: axes.yaxis.max, xaxis: axes.xaxis, yaxis: axes.yaxis, x2axis: axes.x2axis, y2axis: axes.y2axis }); // xmin etc. is backwards compatibility, to be
// removed in the future
axes.xmin = axes.xaxis.min;
axes.xmax = axes.xaxis.max;
axes.ymin = axes.yaxis.min;
axes.ymax = axes.yaxis.max;
markings = markings(axes);
}
for (i = 0; i < markings.length; ++i) { for (i = 0; i < markings.length; ++i) {
var m = markings[i], var m = markings[i],
...@@ -1167,8 +1423,6 @@ ...@@ -1167,8 +1423,6 @@
ctx.beginPath(); ctx.beginPath();
ctx.strokeStyle = m.color || options.grid.markingsColor; ctx.strokeStyle = m.color || options.grid.markingsColor;
ctx.lineWidth = m.lineWidth || options.grid.markingsLineWidth; ctx.lineWidth = m.lineWidth || options.grid.markingsLineWidth;
//ctx.moveTo(Math.floor(xrange.from), yrange.from);
//ctx.lineTo(Math.floor(xrange.to), yrange.to);
ctx.moveTo(xrange.from, yrange.from); ctx.moveTo(xrange.from, yrange.from);
ctx.lineTo(xrange.to, yrange.to); ctx.lineTo(xrange.to, yrange.to);
ctx.stroke(); ctx.stroke();
...@@ -1183,59 +1437,94 @@ ...@@ -1183,59 +1437,94 @@
} }
} }
// draw the inner grid // draw the ticks
ctx.lineWidth = 1;
ctx.strokeStyle = options.grid.tickColor; ctx.strokeStyle = options.grid.tickColor;
ctx.beginPath(); var axes = getUsedAxes(), bw = options.grid.borderWidth;
var v, axis = axes.xaxis,
bw = options.grid.borderWidth; for (var j = 0; j < axes.length; ++j) {
for (i = 0; i < axis.ticks.length; ++i) { var axis = axes[j], box = axis.box,
v = axis.ticks[i].v; t = axis.tickLength, x, y, xoff, yoff;
if (v < axis.min || v > axis.max ||
(bw > 0 && (v == axis.min || v == axis.max)))
continue; // skip those lying on the axes if we got a border
ctx.moveTo(Math.floor(axis.p2c(v)) + ctx.lineWidth/2, 0); // find the edges
ctx.lineTo(Math.floor(axis.p2c(v)) + ctx.lineWidth/2, plotHeight); if (axis.direction == "x") {
x = 0;
if (axis.position == "bottom")
y = box.top - plotOffset.top;
else
y = box.top - plotOffset.top + box.height;
}
else {
y = 0;
if (axis.position == "left")
x = box.left - plotOffset.left + box.width;
else
x = box.left - plotOffset.left;
} }
axis = axes.yaxis; ctx.lineWidth = 1;
for (i = 0; i < axis.ticks.length; ++i) {
v = axis.ticks[i].v; // draw tick bar
if (v < axis.min || v > axis.max || if (!axis.innermost) {
(bw > 0 && (v == axis.min || v == axis.max))) ctx.beginPath();
continue; xoff = yoff = 0;
if (axis.direction == "x")
xoff = plotWidth;
else
yoff = plotHeight;
ctx.moveTo(0, Math.floor(axis.p2c(v)) + ctx.lineWidth/2); if (ctx.lineWidth == 1) {
ctx.lineTo(plotWidth, Math.floor(axis.p2c(v)) + ctx.lineWidth/2); x = Math.floor(x) + 0.5;
y = Math.floor(y) + 0.5;
}
ctx.moveTo(x, y);
ctx.lineTo(x + xoff, y + yoff);
ctx.stroke();
} }
axis = axes.x2axis; // draw ticks
ctx.beginPath();
for (i = 0; i < axis.ticks.length; ++i) { for (i = 0; i < axis.ticks.length; ++i) {
v = axis.ticks[i].v; var v = axis.ticks[i].v;
if (v < axis.min || v > axis.max ||
(bw > 0 && (v == axis.min || v == axis.max))) xoff = yoff = 0;
if (v < axis.min || v > axis.max
// skip those lying on the axes if we got a border
|| (t == "full" && bw > 0
&& (v == axis.min || v == axis.max)))
continue; continue;
ctx.moveTo(Math.floor(axis.p2c(v)) + ctx.lineWidth/2, -5); if (axis.direction == "x") {
ctx.lineTo(Math.floor(axis.p2c(v)) + ctx.lineWidth/2, 5); x = axis.p2c(v);
yoff = t == "full" ? -plotHeight : t;
if (axis.position == "top")
yoff = -yoff;
}
else {
y = axis.p2c(v);
xoff = t == "full" ? -plotWidth : t;
if (axis.position == "left")
xoff = -xoff;
} }
axis = axes.y2axis; if (ctx.lineWidth == 1) {
for (i = 0; i < axis.ticks.length; ++i) { x = Math.floor(x) + 0.5;
v = axis.ticks[i].v; y = Math.floor(y) + 0.5;
if (v < axis.min || v > axis.max || }
(bw > 0 && (v == axis.min || v == axis.max)))
continue;
ctx.moveTo(plotWidth-5, Math.floor(axis.p2c(v)) + ctx.lineWidth/2); ctx.moveTo(x, y);
ctx.lineTo(plotWidth+5, Math.floor(axis.p2c(v)) + ctx.lineWidth/2); ctx.lineTo(x + xoff, y + yoff);
} }
ctx.stroke(); ctx.stroke();
}
if (options.grid.borderWidth) {
// draw border // draw border
if (bw) {
ctx.lineWidth = bw; ctx.lineWidth = bw;
ctx.strokeStyle = options.grid.borderColor; ctx.strokeStyle = options.grid.borderColor;
ctx.strokeRect(-bw/2, -bw/2, plotWidth + bw, plotHeight + bw); ctx.strokeRect(-bw/2, -bw/2, plotWidth + bw, plotHeight + bw);
...@@ -1244,38 +1533,53 @@ ...@@ -1244,38 +1533,53 @@
ctx.restore(); ctx.restore();
} }
function insertLabels() { function insertAxisLabels() {
placeholder.find(".tickLabels").remove(); placeholder.find(".tickLabels").remove();
var html = ['<div class="tickLabels" style="font-size:smaller;color:' + options.grid.color + '">']; var html = ['<div class="tickLabels" style="font-size:smaller;color:' + options.grid.color + '">'];
function addLabels(axis, labelGenerator) { var axes = getUsedAxes();
for (var j = 0; j < axes.length; ++j) {
var axis = axes[j], box = axis.box;
//debug: html.push('<div style="position:absolute;opacity:0.10;background-color:red;left:' + box.left + 'px;top:' + box.top + 'px;width:' + box.width + 'px;height:' + box.height + 'px"></div>')
html.push('<div class="' + axis.direction + 'Axis ' + axis.direction + axis.n + 'Axis">');
for (var i = 0; i < axis.ticks.length; ++i) { for (var i = 0; i < axis.ticks.length; ++i) {
var tick = axis.ticks[i]; var tick = axis.ticks[i];
if (!tick.label || tick.v < axis.min || tick.v > axis.max) if (!tick.label || tick.v < axis.min || tick.v > axis.max)
continue; continue;
html.push(labelGenerator(tick, axis));
}
}
var margin = options.grid.labelMargin + options.grid.borderWidth;
addLabels(axes.xaxis, function (tick, axis) { var pos = {}, align;
return '<div style="position:absolute;top:' + (plotOffset.top + plotHeight + margin) + 'px;left:' + Math.round(plotOffset.left + axis.p2c(tick.v) - axis.labelWidth/2) + 'px;width:' + axis.labelWidth + 'px;text-align:center" class="tickLabel">' + tick.label + "</div>";
});
if (axis.direction == "x") {
align = "center";
pos.left = Math.round(plotOffset.left + axis.p2c(tick.v) - axis.labelWidth/2);
if (axis.position == "bottom")
pos.top = box.top + box.padding;
else
pos.bottom = canvasHeight - (box.top + box.height - box.padding);
}
else {
pos.top = Math.round(plotOffset.top + axis.p2c(tick.v) - axis.labelHeight/2);
if (axis.position == "left") {
pos.right = canvasWidth - (box.left + box.width - box.padding)
align = "right";
}
else {
pos.left = box.left + box.padding;
align = "left";
}
}
addLabels(axes.yaxis, function (tick, axis) { pos.width = axis.labelWidth;
return '<div style="position:absolute;top:' + Math.round(plotOffset.top + axis.p2c(tick.v) - axis.labelHeight/2) + 'px;right:' + (plotOffset.right + plotWidth + margin) + 'px;width:' + axis.labelWidth + 'px;text-align:right" class="tickLabel">' + tick.label + "</div>";
});
addLabels(axes.x2axis, function (tick, axis) { var style = ["position:absolute", "text-align:" + align ];
return '<div style="position:absolute;bottom:' + (plotOffset.bottom + plotHeight + margin) + 'px;left:' + Math.round(plotOffset.left + axis.p2c(tick.v) - axis.labelWidth/2) + 'px;width:' + axis.labelWidth + 'px;text-align:center" class="tickLabel">' + tick.label + "</div>"; for (var a in pos)
}); style.push(a + ":" + pos[a] + "px")
addLabels(axes.y2axis, function (tick, axis) { html.push('<div style="' + style.join(';') + '">' + tick.label + '</div>');
return '<div style="position:absolute;top:' + Math.round(plotOffset.top + axis.p2c(tick.v) - axis.labelHeight/2) + 'px;left:' + (plotOffset.left + plotWidth + margin) +'px;width:' + axis.labelWidth + 'px;text-align:left" class="tickLabel">' + tick.label + "</div>"; }
}); html.push('</div>');
}
html.push('</div>'); html.push('</div>');
...@@ -1912,18 +2216,12 @@ ...@@ -1912,18 +2216,12 @@
// so we share their code) // so we share their code)
function triggerClickHoverEvent(eventname, event, seriesFilter) { function triggerClickHoverEvent(eventname, event, seriesFilter) {
var offset = eventHolder.offset(), var offset = eventHolder.offset(),
pos = { pageX: event.pageX, pageY: event.pageY },
canvasX = event.pageX - offset.left - plotOffset.left, canvasX = event.pageX - offset.left - plotOffset.left,
canvasY = event.pageY - offset.top - plotOffset.top; canvasY = event.pageY - offset.top - plotOffset.top,
pos = canvasToAxisCoords({ left: canvasX, top: canvasY });
if (axes.xaxis.used) pos.pageX = event.pageX;
pos.x = axes.xaxis.c2p(canvasX); pos.pageY = event.pageY;
if (axes.yaxis.used)
pos.y = axes.yaxis.c2p(canvasY);
if (axes.x2axis.used)
pos.x2 = axes.x2axis.c2p(canvasX);
if (axes.y2axis.used)
pos.y2 = axes.y2axis.c2p(canvasY);
var item = findNearbyItem(canvasX, canvasY, seriesFilter); var item = findNearbyItem(canvasX, canvasY, seriesFilter);
...@@ -2078,14 +2376,9 @@ ...@@ -2078,14 +2376,9 @@
} }
$.plot = function(placeholder, data, options) { $.plot = function(placeholder, data, options) {
//var t0 = new Date();
var plot = new Plot($(placeholder), data, options, $.plot.plugins); var plot = new Plot($(placeholder), data, options, $.plot.plugins);
/*var t0 = new Date(); //(window.console ? console.log : alert)("time used (msecs): " + ((new Date()).getTime() - t0.getTime()));
var t1 = new Date();
var tstr = "time used (msecs): " + (t1.getTime() - t0.getTime())
if (window.console)
console.log(tstr);
else
alert(tstr);*/
return plot; return plot;
}; };
......
...@@ -64,7 +64,7 @@ Example API usage: ...@@ -64,7 +64,7 @@ Example API usage:
Here, "center" specifies where the center of the zooming should Here, "center" specifies where the center of the zooming should
happen. Note that this is defined in pixel space, not the space of the happen. Note that this is defined in pixel space, not the space of the
data points (you can use the c2p helpers on the axes in Flot to help data points (you can use the p2c helpers on the axes in Flot to help
you convert between these). you convert between these).
"amount" is the amount to zoom the viewport relative to the current "amount" is the amount to zoom the viewport relative to the current
...@@ -192,51 +192,49 @@ Licensed under the MIT License ~ http://threedubmedia.googlecode.com/files/MIT-L ...@@ -192,51 +192,49 @@ Licensed under the MIT License ~ http://threedubmedia.googlecode.com/files/MIT-L
if (!args) if (!args)
args = {}; args = {};
var axes = plot.getAxes(), var c = args.center,
options = plot.getOptions(), amount = args.amount || plot.getOptions().zoom.amount,
c = args.center,
amount = args.amount ? args.amount : options.zoom.amount,
w = plot.width(), h = plot.height(); w = plot.width(), h = plot.height();
if (!c) if (!c)
c = { left: w / 2, top: h / 2 }; c = { left: w / 2, top: h / 2 };
var xf = c.left / w, var xf = c.left / w,
x1 = c.left - xf * w / amount,
x2 = c.left + (1 - xf) * w / amount,
yf = c.top / h, yf = c.top / h,
y1 = c.top - yf * h / amount, minmax = {
y2 = c.top + (1 - yf) * h / amount; x: {
min: c.left - xf * w / amount,
max: c.left + (1 - xf) * w / amount
},
y: {
min: c.top - yf * h / amount,
max: c.top + (1 - yf) * h / amount
}
};
function scaleAxis(min, max, name) { $.each(plot.getUsedAxes(), function(i, axis) {
var axis = axes[name], var opts = axis.options,
axisOptions = options[name]; min = minmax[axis.direction].min,
max = minmax[axis.direction].max
if (!axis.used)
return;
min = axis.c2p(min); min = axis.c2p(min);
max = axis.c2p(max); max = axis.c2p(max);
if (max < min) { // make sure min < max if (min > max) {
var tmp = min // make sure min < max
var tmp = min;
min = max; min = max;
max = tmp; max = tmp;
} }
var range = max - min, zr = axisOptions.zoomRange; var range = max - min, zr = opts.zoomRange;
if (zr && if (zr &&
((zr[0] != null && range < zr[0]) || ((zr[0] != null && range < zr[0]) ||
(zr[1] != null && range > zr[1]))) (zr[1] != null && range > zr[1])))
return; return;
axisOptions.min = min; opts.min = min;
axisOptions.max = max; opts.max = max;
} });
scaleAxis(x1, x2, 'xaxis');
scaleAxis(x1, x2, 'x2axis');
scaleAxis(y1, y2, 'yaxis');
scaleAxis(y1, y2, 'y2axis');
plot.setupGrid(); plot.setupGrid();
plot.draw(); plot.draw();
...@@ -246,49 +244,42 @@ Licensed under the MIT License ~ http://threedubmedia.googlecode.com/files/MIT-L ...@@ -246,49 +244,42 @@ Licensed under the MIT License ~ http://threedubmedia.googlecode.com/files/MIT-L
} }
plot.pan = function (args) { plot.pan = function (args) {
var l = +args.left, t = +args.top, var delta = {
axes = plot.getAxes(), options = plot.getOptions(); x: +args.left,
y: +args.top
if (isNaN(l)) };
l = 0;
if (isNaN(t))
t = 0;
function panAxis(delta, name) { if (isNaN(delta.x))
var axis = axes[name], delta.x = 0;
axisOptions = options[name], if (isNaN(delta.y))
min, max; delta.y = 0;
if (!axis.used) $.each(plot.getUsedAxes(), function (i, axis) {
return; var opts = axis.options,
min, max, d = delta[axis.direction];
min = axis.c2p(axis.p2c(axis.min) + delta), min = axis.c2p(axis.p2c(axis.min) + d),
max = axis.c2p(axis.p2c(axis.max) + delta); max = axis.c2p(axis.p2c(axis.max) + d);
var pr = axisOptions.panRange; var pr = opts.panRange;
if (pr) { if (pr) {
// check whether we hit the wall // check whether we hit the wall
if (pr[0] != null && pr[0] > min) { if (pr[0] != null && pr[0] > min) {
delta = pr[0] - min; d = pr[0] - min;
min += delta; min += d;
max += delta; max += d;
} }
if (pr[1] != null && pr[1] < max) { if (pr[1] != null && pr[1] < max) {
delta = pr[1] - max; d = pr[1] - max;
min += delta; min += d;
max += delta; max += d;
} }
} }
axisOptions.min = min; opts.min = min;
axisOptions.max = max; opts.max = max;
} });
panAxis(l, 'xaxis');
panAxis(l, 'x2axis');
panAxis(t, 'yaxis');
panAxis(t, 'y2axis');
plot.setupGrid(); plot.setupGrid();
plot.draw(); plot.draw();
......
...@@ -8,20 +8,20 @@ The plugin defines the following options: ...@@ -8,20 +8,20 @@ The plugin defines the following options:
color: color color: color
} }
You enable selection support by setting the mode to one of "x", "y" or Selection support is enabled by setting the mode to one of "x", "y" or
"xy". In "x" mode, the user will only be able to specify the x range, "xy". In "x" mode, the user will only be able to specify the x range,
similarly for "y" mode. For "xy", the selection becomes a rectangle similarly for "y" mode. For "xy", the selection becomes a rectangle
where both ranges can be specified. "color" is color of the selection. where both ranges can be specified. "color" is color of the selection.
When selection support is enabled, a "plotselected" event will be emitted When selection support is enabled, a "plotselected" event will be
on the DOM element you passed into the plot function. The event emitted on the DOM element you passed into the plot function. The
handler gets one extra parameter with the ranges selected on the axes, event handler gets a parameter with the ranges selected on the axes,
like this: like this:
placeholder.bind("plotselected", function(event, ranges) { placeholder.bind("plotselected", function(event, ranges) {
alert("You selected " + ranges.xaxis.from + " to " + ranges.xaxis.to) alert("You selected " + ranges.xaxis.from + " to " + ranges.xaxis.to)
// similar for yaxis, secondary axes are in x2axis // similar for yaxis - with multiple axes, the extra ones are in
// and y2axis if present // x2axis, x3axis, ...
}); });
The "plotselected" event is only fired when the user has finished The "plotselected" event is only fired when the user has finished
...@@ -37,17 +37,19 @@ The plugin allso adds the following methods to the plot object: ...@@ -37,17 +37,19 @@ The plugin allso adds the following methods to the plot object:
- setSelection(ranges, preventEvent) - setSelection(ranges, preventEvent)
Set the selection rectangle. The passed in ranges is on the same Set the selection rectangle. The passed in ranges is on the same
form as returned in the "plotselected" event. If the selection form as returned in the "plotselected" event. If the selection mode
mode is "x", you should put in either an xaxis (or x2axis) object, is "x", you should put in either an xaxis range, if the mode is "y"
if the mode is "y" you need to put in an yaxis (or y2axis) object you need to put in an yaxis range and both xaxis and yaxis if the
and both xaxis/x2axis and yaxis/y2axis if the selection mode is selection mode is "xy", like this:
"xy", like this:
setSelection({ xaxis: { from: 0, to: 10 }, yaxis: { from: 40, to: 60 } }); setSelection({ xaxis: { from: 0, to: 10 }, yaxis: { from: 40, to: 60 } });
setSelection will trigger the "plotselected" event when called. If setSelection will trigger the "plotselected" event when called. If
you don't want that to happen, e.g. if you're inside a you don't want that to happen, e.g. if you're inside a
"plotselected" handler, pass true as the second parameter. "plotselected" handler, pass true as the second parameter. If you
are using multiple axes, you can specify the ranges on any of those,
e.g. as x2axis/x3axis/... instead of xaxis, the plugin picks the
first one it sees.
- clearSelection(preventEvent) - clearSelection(preventEvent)
...@@ -135,21 +137,13 @@ The plugin allso adds the following methods to the plot object: ...@@ -135,21 +137,13 @@ The plugin allso adds the following methods to the plot object:
if (!selectionIsSane()) if (!selectionIsSane())
return null; return null;
var x1 = Math.min(selection.first.x, selection.second.x), var r = {}, c1 = selection.first, c2 = selection.second;
x2 = Math.max(selection.first.x, selection.second.x), $.each(plot.getAxes(), function (name, axis) {
y1 = Math.max(selection.first.y, selection.second.y), if (axis.used) {
y2 = Math.min(selection.first.y, selection.second.y); var p1 = axis.c2p(c1[axis.direction]), p2 = axis.c2p(c2[axis.direction]);
r[name] = { from: Math.min(p1, p2), to: Math.max(p1, p2) };
var r = {}; }
var axes = plot.getAxes(); });
if (axes.xaxis.used)
r.xaxis = { from: axes.xaxis.c2p(x1), to: axes.xaxis.c2p(x2) };
if (axes.x2axis.used)
r.x2axis = { from: axes.x2axis.c2p(x1), to: axes.x2axis.c2p(x2) };
if (axes.yaxis.used)
r.yaxis = { from: axes.yaxis.c2p(y1), to: axes.yaxis.c2p(y2) };
if (axes.y2axis.used)
r.y2axis = { from: axes.y2axis.c2p(y1), to: axes.y2axis.c2p(y2) };
return r; return r;
} }
...@@ -159,13 +153,12 @@ The plugin allso adds the following methods to the plot object: ...@@ -159,13 +153,12 @@ The plugin allso adds the following methods to the plot object:
plot.getPlaceholder().trigger("plotselected", [ r ]); plot.getPlaceholder().trigger("plotselected", [ r ]);
// backwards-compat stuff, to be removed in future // backwards-compat stuff, to be removed in future
var axes = plot.getAxes(); if (r.xaxis && r.yaxis)
if (axes.xaxis.used && axes.yaxis.used)
plot.getPlaceholder().trigger("selected", [ { x1: r.xaxis.from, y1: r.yaxis.from, x2: r.xaxis.to, y2: r.yaxis.to } ]); plot.getPlaceholder().trigger("selected", [ { x1: r.xaxis.from, y1: r.yaxis.from, x2: r.xaxis.to, y2: r.yaxis.to } ]);
} }
function clamp(min, value, max) { function clamp(min, value, max) {
return value < min? min: (value > max? max: value); return value < min ? min: (value > max ? max: value);
} }
function setSelectionPos(pos, e) { function setSelectionPos(pos, e) {
...@@ -176,10 +169,10 @@ The plugin allso adds the following methods to the plot object: ...@@ -176,10 +169,10 @@ The plugin allso adds the following methods to the plot object:
pos.y = clamp(0, e.pageY - offset.top - plotOffset.top, plot.height()); pos.y = clamp(0, e.pageY - offset.top - plotOffset.top, plot.height());
if (o.selection.mode == "y") if (o.selection.mode == "y")
pos.x = pos == selection.first? 0: plot.width(); pos.x = pos == selection.first ? 0 : plot.width();
if (o.selection.mode == "x") if (o.selection.mode == "x")
pos.y = pos == selection.first? 0: plot.height(); pos.y = pos == selection.first ? 0 : plot.height();
} }
function updateSelection(pos) { function updateSelection(pos) {
...@@ -204,19 +197,55 @@ The plugin allso adds the following methods to the plot object: ...@@ -204,19 +197,55 @@ The plugin allso adds the following methods to the plot object:
} }
} }
// taken from markings support
function extractRange(ranges, coord) {
var axis, from, to, axes, key;
axes = plot.getUsedAxes();
for (i = 0; i < axes.length; ++i) {
axis = axes[i];
if (axis.direction == coord) {
key = coord + axis.n + "axis";
if (!ranges[key] && axis.n == 1)
key = coord + "axis"; // support x1axis as xaxis
if (ranges[key]) {
from = ranges[key].from;
to = ranges[key].to;
break;
}
}
}
// backwards-compat stuff - to be removed in future
if (!ranges[key]) {
axis = coord == "x" ? plot.getXAxes()[0] : plot.getYAxes()[0];
from = ranges[coord + "1"];
to = ranges[coord + "2"];
}
// auto-reverse as an added bonus
if (from != null && to != null && from > to) {
var tmp = from;
from = to;
to = tmp;
}
return { from: from, to: to, axis: axis };
}
function setSelection(ranges, preventEvent) { function setSelection(ranges, preventEvent) {
var axis, range, axes = plot.getAxes(); var axis, range, o = plot.getOptions();
var o = plot.getOptions();
if (o.selection.mode == "y") { if (o.selection.mode == "y") {
selection.first.x = 0; selection.first.x = 0;
selection.second.x = plot.width(); selection.second.x = plot.width();
} }
else { else {
axis = ranges["xaxis"]? axes["xaxis"]: (ranges["x2axis"]? axes["x2axis"]: axes["xaxis"]); range = extractRange(ranges, "x");
range = ranges["xaxis"] || ranges["x2axis"] || { from:ranges["x1"], to:ranges["x2"] }
selection.first.x = axis.p2c(Math.min(range.from, range.to)); selection.first.x = range.axis.p2c(range.from);
selection.second.x = axis.p2c(Math.max(range.from, range.to)); selection.second.x = range.axis.p2c(range.to);
} }
if (o.selection.mode == "x") { if (o.selection.mode == "x") {
...@@ -224,10 +253,10 @@ The plugin allso adds the following methods to the plot object: ...@@ -224,10 +253,10 @@ The plugin allso adds the following methods to the plot object:
selection.second.y = plot.height(); selection.second.y = plot.height();
} }
else { else {
axis = ranges["yaxis"]? axes["yaxis"]: (ranges["y2axis"]? axes["y2axis"]: axes["yaxis"]); range = extractRange(ranges, "y");
range = ranges["yaxis"] || ranges["y2axis"] || { from:ranges["y1"], to:ranges["y2"] }
selection.first.y = axis.p2c(Math.min(range.from, range.to)); selection.first.y = range.axis.p2c(range.from);
selection.second.y = axis.p2c(Math.max(range.from, range.to)); selection.second.y = range.axis.p2c(range.to);
} }
selection.show = true; selection.show = true;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment