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

Move selection support to a plugin (based on patch from andershol),

move color code to separate jQuery plugin inlined in the Flot code
(and hosted here for the time being), fixup some various other little
things in preparation for the 0.6 release


git-svn-id: https://flot.googlecode.com/svn/trunk@220 1e0a6537-2640-0410-bfb7-f154510ff394
parent bc2bcd1b
...@@ -665,39 +665,6 @@ can set "hoverable" and "clickable" to false in the options for that ...@@ -665,39 +665,6 @@ can set "hoverable" and "clickable" to false in the options for that
series, like this { data: [...], label: "Foo", clickable: false }. series, like this { data: [...], label: "Foo", clickable: false }.
Customizing the selection
=========================
selection: {
mode: null or "x" or "y" or "xy",
color: color
}
You enable selection support 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,
similarly for "y" mode. For "xy", the selection becomes a rectangle
where both ranges can be specified. "color" is color of the selection.
When selection support is enabled, a "plotselected" event will be emitted
on the DOM element you passed into the plot function. The event
handler gets one extra parameter with the ranges selected on the axes,
like this:
placeholder.bind("plotselected", function(event, ranges) {
alert("You selected " + ranges.xaxis.from + " to " + ranges.xaxis.to)
// similar for yaxis, secondary axes are in x2axis
// and y2axis if present
});
The "plotselected" event is only fired when the user has finished
making the selection. A "plotselecting" event is fired during the
process with the same parameters as the "plotselected" event, in case
you want to know what's happening while it's happening,
A "plotunselected" event with no arguments is emitted when the user
clicks the mouse to remove the selection.
Specifying gradients Specifying gradients
==================== ====================
...@@ -739,34 +706,6 @@ Plot Methods ...@@ -739,34 +706,6 @@ Plot Methods
The Plot object returned from the plot function has some methods you The Plot object returned from the plot function has some methods you
can call: can call:
- setSelection(ranges, preventEvent)
Set the selection rectangle. The passed in ranges is on the same
form as returned in the "plotselected" event. If the selection
mode is "x", you should put in either an xaxis (or x2axis) object,
if the mode is "y" you need to put in an yaxis (or y2axis) object
and both xaxis/x2axis and yaxis/y2axis if the selection mode is
"xy", like this:
setSelection({ xaxis: { from: 0, to: 10 }, yaxis: { from: 40, to: 60 } });
setSelection will trigger the "plotselected" event when called. If
you don't want that to happen, e.g. if you're inside a
"plotselected" handler, pass true as the second parameter.
- clearSelection(preventEvent)
Clear the selection rectangle. Pass in true to avoid getting a
"plotunselected" event.
- getSelection()
Returns the current selection in the same format as the
"plotselected" event. If there's currently no selection, it
returns null.
- highlight(series, datapoint) - highlight(series, datapoint)
Highlight a specific datapoint in the data series. You can either Highlight a specific datapoint in the data series. You can either
...@@ -815,7 +754,7 @@ can call: ...@@ -815,7 +754,7 @@ can call:
- triggerRedrawOverlay() - triggerRedrawOverlay()
Schedules an update of an overlay canvas used for drawing Schedules an update of an overlay canvas used for drawing
interactive things like the selection and point highlights. This interactive things like a selection and point highlights. This
is mostly useful for writing plugins. The redraw doesn't happen is mostly useful for writing plugins. The redraw doesn't happen
immediately, instead a timer is set to catch multiple successive immediately, instead a timer is set to catch multiple successive
redraws (e.g. from a mousemove). redraws (e.g. from a mousemove).
......
Flot 0.x Flot 0.6
-------- --------
API changes: API changes:
1. In the global options specified in the $.plot command, 1. Selection support has been moved to a plugin. Thus if you're
passing selection: { mode: something }, you MUST include the file
jquery.flot.selection.js after jquery.flot.js. This reduces the size
of base Flot and makes it easier to customize the selection as well as
improving code clarity. The change is based on patch from andershol.
2. In the global options specified in the $.plot command,
"lines", "points", "bars" and "shadowSize" have been moved to a "lines", "points", "bars" and "shadowSize" have been moved to a
sub-object called "series", i.e. sub-object called "series", i.e.
$.plot(placeholder, data, { lines: { show: true }}) $.plot(placeholder, data, { lines: { show: true }})
becomes should be changed to
$.plot(placeholder, data, { series: { lines: { show: true }}}) $.plot(placeholder, data, { series: { lines: { show: true }}})
All future series-specific options will go into this sub-object to All future series-specific options will go into this sub-object to
simplify plugin writing. Backward-compatibility hooks are in place, simplify plugin writing. Backward-compatibility code is in place, so
so old code should not break. old code should not break.
2. "plothover" no longer provides the original data point, but instead 3. "plothover" no longer provides the original data point, but instead
a normalized one, since there may be no corresponding original point. a normalized one, since there may be no corresponding original point.
3. Due to a bug in previous versions of jQuery, you now need at least 4. Due to a bug in previous versions of jQuery, you now need at least
jQuery 1.2.6. But if you can, try jQuery 1.3.2 as it got some jQuery 1.2.6. But if you can, try jQuery 1.3.2 as it got some
improvements in event handling speed. improvements in event handling speed.
...@@ -85,9 +91,9 @@ Changes: ...@@ -85,9 +91,9 @@ Changes:
offset within the placeholder. offset within the placeholder.
- Plugin system: register an init method in the $.flot.plugins array - Plugin system: register an init method in the $.flot.plugins array
to get started, see PLUGINS.txt for details on how to write plugins. to get started, see PLUGINS.txt for details on how to write plugins
There are also some extra methods to enable access to internal (it's easy). There are also some extra methods to enable access to
state. internal state.
- Hooks: you can register functions that are called while Flot is - Hooks: you can register functions that are called while Flot is
crunching the data and doing the plot. This can be used to modify crunching the data and doing the plot. This can be used to modify
...@@ -115,7 +121,12 @@ Changes: ...@@ -115,7 +121,12 @@ Changes:
axes and compressed time axes (like omitting weekends). axes and compressed time axes (like omitting weekends).
- Support for twelve-hour date formatting (patch by Forrest Aldridge). - Support for twelve-hour date formatting (patch by Forrest Aldridge).
- The color parsing code in Flot has been cleaned up and split out so
it's now available as a separate jQuery plugin. It's included inline
in the Flot source to make dependency managing easier. This also
makes it really easy to use the color helpers in Flot plugins.
Bug fixes: Bug fixes:
- Fixed two corner-case bugs when drawing filled curves (report and - Fixed two corner-case bugs when drawing filled curves (report and
...@@ -130,7 +141,7 @@ Bug fixes: ...@@ -130,7 +141,7 @@ Bug fixes:
problem reported by Sergio Nunes). problem reported by Sergio Nunes).
- Updated mousemove position expression to the latest from jQuery (bug - Updated mousemove position expression to the latest from jQuery (bug
reported by meyuchas). reported by meyuchas).
- Use borders instead of background in legend (fix printing issue 25 - Use CSS borders instead of background in legend (fix printing issue 25
and 45). and 45).
- Explicitly convert axis min/max to numbers. - Explicitly convert axis min/max to numbers.
- Fixed a bug with drawing marking lines with different colors - Fixed a bug with drawing marking lines with different colors
......
...@@ -21,16 +21,28 @@ ...@@ -21,16 +21,28 @@
<script id="source" language="javascript" type="text/javascript"> <script id="source" language="javascript" type="text/javascript">
$(function () { $(function () {
var d1 = []; var c = 0;
for (var i = 0; i < 14; i += 0.5)
d1.push([i, Math.sin(i)]); function plot() {
++c;
var d1 = [];
for (var i = 0; i < 14; i += 0.5)
d1.push([i, Math.sin(i)]);
var d2 = [[0, 3], [4, 8], [8, 5], [9, 13]];
var d2 = [[0, 3], [4, 8], [8, 5], [9, 13]]; // a null signifies separate line segments
var d3 = [[0, 12], [7, 12], null, [7, 2.5], [12, 2.5]];
// a null signifies separate line segments $.plot($("#placeholder"), [ d1, d2, d3 ]);
var d3 = [[0, 12], [7, 12], null, [7, 2.5], [12, 2.5]];
$.plot($("#placeholder"), [ d1, d2, d3 ]); $("p").text("" +c);
if (c < 1000)
setTimeout(plot, 10);
}
plot();
}); });
</script> </script>
......
...@@ -28,7 +28,8 @@ $(function () { ...@@ -28,7 +28,8 @@ $(function () {
$.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' }, {
xaxis: { mode: 'time' },
yaxis: { min: 0 }, yaxis: { min: 0 },
y2axis: { tickFormatter: function (v, axis) { return v.toFixed(axis.tickDecimals) +"€" }}, y2axis: { tickFormatter: function (v, axis) { return v.toFixed(axis.tickDecimals) +"€" }},
legend: { position: 'sw' } }); legend: { position: 'sw' } });
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
<body> <body>
<h1>Flot Examples</h1> <h1>Flot Examples</h1>
<p>Here are some examples for <a href="http://code.google.com/p/flot/">Flot</a>:</p> <p>Here are some examples for <a href="http://code.google.com/p/flot/">Flot</a>, the Javascript charting library for jQuery:</p>
<ul> <ul>
<li><a href="basic.html">Basic example</a></li> <li><a href="basic.html">Basic example</a></li>
...@@ -24,20 +24,20 @@ ...@@ -24,20 +24,20 @@
<ul> <ul>
<li><a href="turning-series.html">Turning series on/off</a></li> <li><a href="turning-series.html">Turning series on/off</a></li>
<li><a href="selection.html">Selection support and zooming</a> and <a href="zooming.html">zooming with overview</a></li> <li><a href="selection.html">Rectangular selection support and zooming</a> and <a href="zooming.html">zooming with overview</a></li> (both with selection plugin)
<li><a href="interacting.html">Interacting with the data points</a></li> <li><a href="interacting.html">Interacting with the data points</a></li>
<li><a href="navigate.html">Panning and zooming</a> (with plugin)</li> <li><a href="navigate.html">Panning and zooming</a> (with navigation plugin)</li>
</ul> </ul>
<p>Some more esoteric features:</p> <p>Some more esoteric features:</p>
<ul> <ul>
<li><a href="time.html">Plotting time series</a> and <a href="visitors.html">visitors per day with zooming and weekends</a></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="dual-axis.html">Dual axis support</a></li>
<li><a href="thresholding.html">Thresholding the data</a> (with plugin)</li> <li><a href="thresholding.html">Thresholding the data</a> (with threshold plugin)</li>
<li><a href="stacking.html">Stacked charts</a> (with plugin)</li> <li><a href="stacking.html">Stacked charts</a> (with stacking plugin)</li>
<li><a href="tracking.html">Tracking curves with crosshair</a> (with plugin)</li> <li><a href="tracking.html">Tracking curves with crosshair</a> (with crosshair plugin)</li>
<li><a href="image.html">Plotting prerendered images</a> (with plugin)</li> <li><a href="image.html">Plotting prerendered images</a> (with image plugin)</li>
</ul> </ul>
</body> </body>
</html> </html>
...@@ -38,7 +38,6 @@ $(function () { ...@@ -38,7 +38,6 @@ $(function () {
lines: { show: true }, lines: { show: true },
points: { show: true } points: { show: true }
}, },
selection: { mode: "xy" },
grid: { hoverable: true, clickable: true }, grid: { hoverable: true, clickable: true },
yaxis: { min: -1.2, max: 1.2 } yaxis: { min: -1.2, max: 1.2 }
}); });
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
<!--[if IE]><script language="javascript" type="text/javascript" src="../excanvas.min.js"></script><![endif]--> <!--[if IE]><script language="javascript" type="text/javascript" src="../excanvas.min.js"></script><![endif]-->
<script language="javascript" type="text/javascript" src="../jquery.js"></script> <script language="javascript" type="text/javascript" src="../jquery.js"></script>
<script language="javascript" type="text/javascript" src="../jquery.flot.js"></script> <script language="javascript" type="text/javascript" src="../jquery.flot.js"></script>
<script language="javascript" type="text/javascript" src="../jquery.flot.selection.js"></script>
</head> </head>
<body> <body>
<h1>Flot Examples</h1> <h1>Flot Examples</h1>
...@@ -15,23 +16,23 @@ ...@@ -15,23 +16,23 @@
<p>1000 kg. CO<sub>2</sub> emissions per year per capita for various countries (source: <a href="http://en.wikipedia.org/wiki/List_of_countries_by_carbon_dioxide_emissions_per_capita">Wikipedia</a>).</p> <p>1000 kg. CO<sub>2</sub> emissions per year per capita for various countries (source: <a href="http://en.wikipedia.org/wiki/List_of_countries_by_carbon_dioxide_emissions_per_capita">Wikipedia</a>).</p>
<p>Flot supports selections. You can enable <p>Flot supports selections through the selection plugin.
rectangular selection You can enable rectangular selection
or one-dimensional selection if the user should only be able to or one-dimensional selection if the user should only be able to
select on one axis. Try left-clicking and drag on the plot above select on one axis. Try left-click and drag on the plot above
where selection on the x axis is enabled.</p> where selection on the x axis is enabled.</p>
<p>You selected: <span id="selection"></span></p> <p>You selected: <span id="selection"></span></p>
<p>The plot command returns a Plot object you can use to control <p>The plot command returns a plot object you can use to control
the selection. Try clicking the buttons below.</p> the selection. Click the buttons below.</p>
<p><input id="clearSelection" type="button" value="Clear selection" /> <p><input id="clearSelection" type="button" value="Clear selection" />
<input id="setSelection" type="button" value="Select year 1994" /></p> <input id="setSelection" type="button" value="Select year 1994" /></p>
<p>Selections are really useful for zooming. Just replot the <p>Selections are really useful for zooming. Just replot the
chart with min and max values for the axes set to the values chart with min and max values for the axes set to the values
in the "plotselected" event triggered. Try enabling the checkbox in the "plotselected" event triggered. Enable the checkbox
below and select a region again.</p> below and select a region again.</p>
<p><input id="zoom" type="checkbox">Zoom to selection.</input></p> <p><input id="zoom" type="checkbox">Zoom to selection.</input></p>
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
<!--[if IE]><script language="javascript" type="text/javascript" src="../excanvas.min.js"></script><![endif]--> <!--[if IE]><script language="javascript" type="text/javascript" src="../excanvas.min.js"></script><![endif]-->
<script language="javascript" type="text/javascript" src="../jquery.js"></script> <script language="javascript" type="text/javascript" src="../jquery.js"></script>
<script language="javascript" type="text/javascript" src="../jquery.flot.js"></script> <script language="javascript" type="text/javascript" src="../jquery.flot.js"></script>
<script language="javascript" type="text/javascript" src="../jquery.flot.selection.js"></script>
</head> </head>
<body> <body>
<h1>Flot Examples</h1> <h1>Flot Examples</h1>
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
<!--[if IE]><script language="javascript" type="text/javascript" src="../excanvas.min.js"></script><![endif]--> <!--[if IE]><script language="javascript" type="text/javascript" src="../excanvas.min.js"></script><![endif]-->
<script language="javascript" type="text/javascript" src="../jquery.js"></script> <script language="javascript" type="text/javascript" src="../jquery.js"></script>
<script language="javascript" type="text/javascript" src="../jquery.flot.js"></script> <script language="javascript" type="text/javascript" src="../jquery.flot.js"></script>
<script language="javascript" type="text/javascript" src="../jquery.flot.selection.js"></script>
</head> </head>
<body> <body>
<h1>Flot Examples</h1> <h1>Flot Examples</h1>
......
...@@ -102,16 +102,18 @@ The plugin also adds four public methods: ...@@ -102,16 +102,18 @@ The plugin also adds four public methods:
}); });
eventHolder.mousemove(function (e) { eventHolder.mousemove(function (e) {
if (!plot.getSelection()) { if (plot.getSelection && plot.getSelection()) {
if (!crosshair.locked) {
var offset = plot.offset();
crosshair.x = Math.max(0, Math.min(e.pageX - offset.left, plot.width()));
crosshair.y = Math.max(0, Math.min(e.pageY - offset.top, plot.height()));
plot.triggerRedrawOverlay();
}
}
else
crosshair.x = -1; // hide the crosshair while selecting crosshair.x = -1; // hide the crosshair while selecting
return;
}
if (crosshair.locked)
return;
var offset = plot.offset();
crosshair.x = Math.max(0, Math.min(e.pageX - offset.left, plot.width()));
crosshair.y = Math.max(0, Math.min(e.pageY - offset.top, plot.height()));
plot.triggerRedrawOverlay();
}); });
}); });
......
/* Javascript plotting library for jQuery, v. 0.5. /* Javascript plotting library for jQuery, v. 0.6.
* *
* Released under the MIT license by IOLA, December 2007. * Released under the MIT license by IOLA, December 2007.
* *
*/ */
// first an inline dependency, jquery.colorhelpers.js, we inline it here
// for convenience
/* Plugin for jQuery for working with colors.
*
* Version 1.0.
*
* Inspiration from jQuery color animation plugin by John Resig.
*
* Released under the MIT license by Ole Laursen, October 2009.
*
* Examples:
*
* $.color.parse("#fff").scale('rgb', 0.25).add('a', -0.5).toString()
* var c = $.color.extract($("#mydiv"), 'background-color');
* console.log(c.r, c.g, c.b, c.a);
* $.color.make(100, 50, 25, 0.4).toString() // returns "rgba(100,50,25,0.4)"
*
* Note that .scale() and .add() work in-place instead of returning
* new objects.
*/
(function(){jQuery.color={};jQuery.color.make=function(E,D,B,C){var F={};F.r=E||0;F.g=D||0;F.b=B||0;F.a=C!=null?C:1;F.add=function(I,H){for(var G=0;G<I.length;++G){F[I.charAt(G)]+=H}return F.normalize()};F.scale=function(I,H){for(var G=0;G<I.length;++G){F[I.charAt(G)]*=H}return F.normalize()};F.toString=function(){if(F.a>=1){return"rgb("+[F.r,F.g,F.b].join(",")+")"}else{return"rgba("+[F.r,F.g,F.b,F.a].join(",")+")"}};F.normalize=function(){function G(I,J,H){return J<I?I:(J>H?H:J)}F.r=G(0,parseInt(F.r),255);F.g=G(0,parseInt(F.g),255);F.b=G(0,parseInt(F.b),255);F.a=G(0,F.a,1);return F};F.clone=function(){return jQuery.color.make(F.r,F.b,F.g,F.a)};return F.normalize()};jQuery.color.extract=function(C,B){var D;do{D=C.css(B).toLowerCase();if(D!=""&&D!="transparent"){break}C=C.parent()}while(!jQuery.nodeName(C.get(0),"body"));if(D=="rgba(0, 0, 0, 0)"){D="transparent"}return jQuery.color.parse(D)};jQuery.color.parse=function(E){var D,B=jQuery.color.make;if(D=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(E)){return B(parseInt(D[1],10),parseInt(D[2],10),parseInt(D[3],10))}if(D=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(E)){return B(parseInt(D[1],10),parseInt(D[2],10),parseInt(D[3],10),parseFloat(D[4]))}if(D=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(E)){return B(parseFloat(D[1])*2.55,parseFloat(D[2])*2.55,parseFloat(D[3])*2.55)}if(D=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(E)){return B(parseFloat(D[1])*2.55,parseFloat(D[2])*2.55,parseFloat(D[3])*2.55,parseFloat(D[4]))}if(D=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(E)){return B(parseInt(D[1],16),parseInt(D[2],16),parseInt(D[3],16))}if(D=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(E)){return B(parseInt(D[1]+D[1],16),parseInt(D[2]+D[2],16),parseInt(D[3]+D[3],16))}var C=jQuery.trim(E).toLowerCase();if(C=="transparent"){return B(255,255,255,0)}else{D=A[C];return B(D[0],D[1],D[2])}};var A={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})();
// the actual Flot code
(function($) { (function($) {
function Plot(placeholder, data_, options_, plugins) { function Plot(placeholder, data_, options_, plugins) {
// data is on the form: // data is on the form:
...@@ -100,10 +124,6 @@ ...@@ -100,10 +124,6 @@
autoHighlight: true, // highlight in case mouse is near autoHighlight: true, // highlight in case mouse is near
mouseActiveRadius: 10 // how far the mouse can be away to activate an item mouseActiveRadius: 10 // how far the mouse can be away to activate an item
}, },
selection: {
mode: null, // one of null, "x", "y" or "xy"
color: "#e8cfac"
},
hooks: {} hooks: {}
}, },
canvas = null, // the canvas for the plot itself canvas = null, // the canvas for the plot itself
...@@ -122,17 +142,12 @@ ...@@ -122,17 +142,12 @@
bindEvents: [], bindEvents: [],
drawOverlay: [] drawOverlay: []
}, },
plot = this, plot = this;
// dedicated to storing data for buggy standard compliance cases
workarounds = {};
// public functions // public functions
plot.setData = setData; plot.setData = setData;
plot.setupGrid = setupGrid; plot.setupGrid = setupGrid;
plot.draw = draw; plot.draw = draw;
plot.clearSelection = clearSelection;
plot.setSelection = setSelection;
plot.getSelection = getSelection;
plot.getPlaceholder = function() { return placeholder; }; plot.getPlaceholder = function() { return placeholder; };
plot.getCanvas = function() { return canvas; }; plot.getCanvas = function() { return canvas; };
plot.getPlotOffset = function() { return plotOffset; }; plot.getPlotOffset = function() { return plotOffset; };
...@@ -263,7 +278,7 @@ ...@@ -263,7 +278,7 @@
if (typeof sc == "number") if (typeof sc == "number")
assignedColors.push(sc); assignedColors.push(sc);
else else
usedColors.push(parseColor(series[i].color)); usedColors.push($.color.parse(series[i].color));
} }
} }
...@@ -279,14 +294,13 @@ ...@@ -279,14 +294,13 @@
while (colors.length < neededColors) { while (colors.length < neededColors) {
var c; var c;
if (options.colors.length == i) // check degenerate case if (options.colors.length == i) // check degenerate case
c = new Color(100, 100, 100); c = $.color.make(100, 100, 100);
else else
c = parseColor(options.colors[i]); c = $.color.parse(options.colors[i]);
// vary color if needed // vary color if needed
var sign = variation % 2 == 1 ? -1 : 1; var sign = variation % 2 == 1 ? -1 : 1;
var factor = 1 + sign * Math.ceil(variation / 2) * 0.2; c.scale('rgb', 1 + sign * Math.ceil(variation / 2) * 0.2)
c.scale(factor, factor, factor);
// FIXME: if we're getting to close to something else, // FIXME: if we're getting to close to something else,
// we should probably skip this one // we should probably skip this one
...@@ -555,13 +569,9 @@ ...@@ -555,13 +569,9 @@
eventHolder = $([overlay, canvas]); eventHolder = $([overlay, canvas]);
// bind events // bind events
if (options.selection.mode != null if (options.grid.hoverable)
|| options.grid.hoverable)
eventHolder.mousemove(onMouseMove); eventHolder.mousemove(onMouseMove);
if (options.selection.mode != null)
eventHolder.mousedown(onMouseDown);
if (options.grid.clickable) if (options.grid.clickable)
eventHolder.click(onClick); eventHolder.click(onClick);
...@@ -1697,7 +1707,7 @@ ...@@ -1697,7 +1707,7 @@
if (filloptions.fillColor) if (filloptions.fillColor)
return getColorOrGradient(filloptions.fillColor, bottom, top, seriesColor); return getColorOrGradient(filloptions.fillColor, bottom, top, seriesColor);
var c = parseColor(seriesColor); var c = $.color.parse(seriesColor);
c.a = typeof fill == "number" ? fill : 0.4; c.a = typeof fill == "number" ? fill : 0.4;
c.normalize(); c.normalize();
return c.toString(); return c.toString();
...@@ -1761,12 +1771,13 @@ ...@@ -1761,12 +1771,13 @@
// label boxes // label boxes
var c = options.legend.backgroundColor; var c = options.legend.backgroundColor;
if (c == null) { if (c == null) {
var tmp; c = options.grid.backgroundColor;
if (options.grid.backgroundColor && typeof options.grid.backgroundColor == "string") if (c && typeof c == "string")
tmp = options.grid.backgroundColor; c = $.color.parse(c);
else else
tmp = extractColor(legend); c = $.color.extract(legend, 'background-color');
c = parseColor(tmp).adjust(null, null, null, 1).toString(); c.a = 1;
c = c.toString();
} }
var div = legend.children(); var div = legend.children();
$('<div style="position:absolute;width:' + div.width() + 'px;height:' + div.height() + 'px;' + pos +'background-color:' + c + ';"> </div>').prependTo(legend).css('opacity', options.legend.backgroundOpacity); $('<div style="position:absolute;width:' + div.width() + 'px;height:' + div.height() + 'px;' + pos +'background-color:' + c + ';"> </div>').prependTo(legend).css('opacity', options.legend.backgroundOpacity);
...@@ -1777,16 +1788,8 @@ ...@@ -1777,16 +1788,8 @@
// interactive features // interactive features
var lastMousePos = { pageX: null, pageY: null }, var highlights = [],
selection = { redrawTimeout = null;
first: { x: -1, y: -1}, second: { x: -1, y: -1},
show: false,
active: false
},
highlights = [],
clickIsMouseUp = false,
redrawTimeout = null,
hoverTimeout = null;
// returns the data item the mouse is over, or null if none is found // returns the data item the mouse is over, or null if none is found
function findNearbyItem(mouseX, mouseY, seriesFilter) { function findNearbyItem(mouseX, mouseY, seriesFilter) {
...@@ -1870,50 +1873,12 @@ ...@@ -1870,50 +1873,12 @@
} }
function onMouseMove(e) { function onMouseMove(e) {
lastMousePos.pageX = e.pageX;
lastMousePos.pageY = e.pageY;
if (options.grid.hoverable) if (options.grid.hoverable)
triggerClickHoverEvent("plothover", lastMousePos, triggerClickHoverEvent("plothover", e,
function (s) { return s["hoverable"] != false; }); function (s) { return s["hoverable"] != false; });
if (selection.active) {
placeholder.trigger("plotselecting", [ getSelection() ]);
updateSelection(lastMousePos);
}
} }
function onMouseDown(e) {
if (e.which != 1) // only accept left-click
return;
// cancel out any text selections
document.body.focus();
// prevent text selection and drag in old-school browsers
if (document.onselectstart !== undefined && workarounds.onselectstart == null) {
workarounds.onselectstart = document.onselectstart;
document.onselectstart = function () { return false; };
}
if (document.ondrag !== undefined && workarounds.ondrag == null) {
workarounds.ondrag = document.ondrag;
document.ondrag = function () { return false; };
}
setSelectionPos(selection.first, e);
lastMousePos.pageX = null;
selection.active = true;
$(document).one("mouseup", onSelectionMouseUp);
}
function onClick(e) { function onClick(e) {
if (clickIsMouseUp) {
clickIsMouseUp = false;
return;
}
triggerClickHoverEvent("plotclick", e, triggerClickHoverEvent("plotclick", e,
function (s) { return s["clickable"] != false; }); function (s) { return s["clickable"] != false; });
} }
...@@ -1981,22 +1946,6 @@ ...@@ -1981,22 +1946,6 @@
else else
drawPointHighlight(hi.series, hi.point); drawPointHighlight(hi.series, hi.point);
} }
// draw selection
if (selection.show && selectionIsSane()) {
octx.strokeStyle = parseColor(options.selection.color).scale(null, null, null, 0.8).toString();
octx.lineWidth = 1;
ctx.lineJoin = "round";
octx.fillStyle = parseColor(options.selection.color).scale(null, null, null, 0.4).toString();
var x = Math.min(selection.first.x, selection.second.x),
y = Math.min(selection.first.y, selection.second.y),
w = Math.abs(selection.second.x - selection.first.x),
h = Math.abs(selection.second.y - selection.first.y);
octx.fillRect(x, y, w, h);
octx.strokeRect(x, y, w, h);
}
octx.restore(); octx.restore();
executeHooks(hooks.drawOverlay, [octx]); executeHooks(hooks.drawOverlay, [octx]);
...@@ -2058,7 +2007,7 @@ ...@@ -2058,7 +2007,7 @@
var pointRadius = series.points.radius + series.points.lineWidth / 2; var pointRadius = series.points.radius + series.points.lineWidth / 2;
octx.lineWidth = pointRadius; octx.lineWidth = pointRadius;
octx.strokeStyle = parseColor(series.color).scale(1, 1, 1, 0.5).toString(); octx.strokeStyle = $.color.parse(series.color).scale('a', 0.5).toString();
var radius = 1.5 * pointRadius; var radius = 1.5 * pointRadius;
octx.beginPath(); octx.beginPath();
octx.arc(axisx.p2c(x), axisy.p2c(y), radius, 0, 2 * Math.PI, false); octx.arc(axisx.p2c(x), axisy.p2c(y), radius, 0, 2 * Math.PI, false);
...@@ -2067,147 +2016,13 @@ ...@@ -2067,147 +2016,13 @@
function drawBarHighlight(series, point) { function drawBarHighlight(series, point) {
octx.lineWidth = series.bars.lineWidth; octx.lineWidth = series.bars.lineWidth;
octx.strokeStyle = parseColor(series.color).scale(1, 1, 1, 0.5).toString(); octx.strokeStyle = $.color.parse(series.color).scale('a', 0.5).toString();
var fillStyle = parseColor(series.color).scale(1, 1, 1, 0.5).toString(); var fillStyle = $.color.parse(series.color).scale('a', 0.5).toString();
var barLeft = series.bars.align == "left" ? 0 : -series.bars.barWidth/2; var barLeft = series.bars.align == "left" ? 0 : -series.bars.barWidth/2;
drawBar(point[0], point[1], point[2] || 0, barLeft, barLeft + series.bars.barWidth, drawBar(point[0], point[1], point[2] || 0, barLeft, barLeft + series.bars.barWidth,
0, function () { return fillStyle; }, series.xaxis, series.yaxis, octx, series.bars.horizontal); 0, function () { return fillStyle; }, series.xaxis, series.yaxis, octx, series.bars.horizontal);
} }
function getSelection() {
if (!selectionIsSane())
return null;
var x1 = Math.min(selection.first.x, selection.second.x),
x2 = Math.max(selection.first.x, selection.second.x),
y1 = Math.max(selection.first.y, selection.second.y),
y2 = Math.min(selection.first.y, selection.second.y);
var r = {};
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;
}
function triggerSelectedEvent() {
var r = getSelection();
placeholder.trigger("plotselected", [ r ]);
// backwards-compat stuff, to be removed in future
if (axes.xaxis.used && axes.yaxis.used)
placeholder.trigger("selected", [ { x1: r.xaxis.from, y1: r.yaxis.from, x2: r.xaxis.to, y2: r.yaxis.to } ]);
}
function onSelectionMouseUp(e) {
// revert drag stuff for old-school browsers
if (document.onselectstart !== undefined)
document.onselectstart = workarounds.onselectstart;
if (document.ondrag !== undefined)
document.ondrag = workarounds.ondrag;
// no more draggy-dee-drag
selection.active = false;
updateSelection(e);
if (selectionIsSane()) {
triggerSelectedEvent();
clickIsMouseUp = true;
}
else {
// this counts as a clear
placeholder.trigger("plotunselected", [ ]);
placeholder.trigger("plotselecting", [ null ]);
}
return false;
}
function setSelectionPos(pos, e) {
var offset = eventHolder.offset();
pos.x = clamp(0, e.pageX - offset.left - plotOffset.left, plotWidth);
pos.y = clamp(0, e.pageY - offset.top - plotOffset.top, plotHeight);
if (options.selection.mode == "y") {
if (pos == selection.first)
pos.x = 0;
else
pos.x = plotWidth;
}
if (options.selection.mode == "x") {
if (pos == selection.first)
pos.y = 0;
else
pos.y = plotHeight;
}
}
function updateSelection(pos) {
if (pos.pageX == null)
return;
setSelectionPos(selection.second, pos);
if (selectionIsSane()) {
selection.show = true;
triggerRedrawOverlay();
}
else
clearSelection(true);
}
function clearSelection(preventEvent) {
if (selection.show) {
selection.show = false;
triggerRedrawOverlay();
if (!preventEvent)
placeholder.trigger("plotunselected", [ ]);
}
}
function setSelection(ranges, preventEvent) {
var range;
if (options.selection.mode == "y") {
selection.first.x = 0;
selection.second.x = plotWidth;
}
else {
range = extractRange(ranges, "x");
selection.first.x = range.axis.p2c(range.from);
selection.second.x = range.axis.p2c(range.to);
}
if (options.selection.mode == "x") {
selection.first.y = 0;
selection.second.y = plotHeight;
}
else {
range = extractRange(ranges, "y");
selection.first.y = range.axis.p2c(range.from);
selection.second.y = range.axis.p2c(range.to);
}
selection.show = true;
triggerRedrawOverlay();
if (!preventEvent)
triggerSelectedEvent();
}
function selectionIsSane() {
var minSize = 5;
return Math.abs(selection.second.x - selection.first.x) >= minSize &&
Math.abs(selection.second.y - selection.first.y) >= minSize;
}
function getColorOrGradient(spec, bottom, top, defaultColor) { function getColorOrGradient(spec, bottom, top, defaultColor) {
if (typeof spec == "string") if (typeof spec == "string")
return spec; return spec;
...@@ -2219,7 +2034,12 @@ ...@@ -2219,7 +2034,12 @@
for (var i = 0, l = spec.colors.length; i < l; ++i) { for (var i = 0, l = spec.colors.length; i < l; ++i) {
var c = spec.colors[i]; var c = spec.colors[i];
gradient.addColorStop(i / (l - 1), typeof c == "string" ? c : parseColor(defaultColor).scale(c.brightness, c.brightness, c.brightness, c.opacity)); if (typeof c != "string") {
c = $.color.parse(defaultColor).scale('rgb', c.brightness);
c.a *= c.opacity;
c = c.toString();
}
gradient.addColorStop(i / (l - 1), c);
} }
return gradient; return gradient;
...@@ -2296,167 +2116,4 @@ ...@@ -2296,167 +2116,4 @@
return base * Math.floor(n / base); return base * Math.floor(n / base);
} }
function clamp(min, value, max) {
if (value < min)
return min;
else if (value > max)
return max;
else
return value;
}
// color helpers, inspiration from the jquery color animation
// plugin by John Resig
function Color (r, g, b, a) {
var rgba = ['r','g','b','a'];
var x = 4; //rgba.length
while (-1<--x) {
this[rgba[x]] = arguments[x] || ((x==3) ? 1.0 : 0);
}
this.toString = function() {
if (this.a >= 1.0) {
return "rgb("+[this.r,this.g,this.b].join(",")+")";
} else {
return "rgba("+[this.r,this.g,this.b,this.a].join(",")+")";
}
};
this.scale = function(rf, gf, bf, af) {
x = 4; //rgba.length
while (-1<--x) {
if (arguments[x] != null)
this[rgba[x]] *= arguments[x];
}
return this.normalize();
};
this.adjust = function(rd, gd, bd, ad) {
x = 4; //rgba.length
while (-1<--x) {
if (arguments[x] != null)
this[rgba[x]] += arguments[x];
}
return this.normalize();
};
this.clone = function() {
return new Color(this.r, this.b, this.g, this.a);
};
this.normalize = function() {
this.r = clamp(0, parseInt(this.r), 255);
this.g = clamp(0, parseInt(this.g), 255);
this.b = clamp(0, parseInt(this.b), 255);
this.a = clamp(0, this.a, 1);
return this;
};
this.normalize();
}
var lookupColors = {
aqua:[0,255,255],
azure:[240,255,255],
beige:[245,245,220],
black:[0,0,0],
blue:[0,0,255],
brown:[165,42,42],
cyan:[0,255,255],
darkblue:[0,0,139],
darkcyan:[0,139,139],
darkgrey:[169,169,169],
darkgreen:[0,100,0],
darkkhaki:[189,183,107],
darkmagenta:[139,0,139],
darkolivegreen:[85,107,47],
darkorange:[255,140,0],
darkorchid:[153,50,204],
darkred:[139,0,0],
darksalmon:[233,150,122],
darkviolet:[148,0,211],
fuchsia:[255,0,255],
gold:[255,215,0],
green:[0,128,0],
indigo:[75,0,130],
khaki:[240,230,140],
lightblue:[173,216,230],
lightcyan:[224,255,255],
lightgreen:[144,238,144],
lightgrey:[211,211,211],
lightpink:[255,182,193],
lightyellow:[255,255,224],
lime:[0,255,0],
magenta:[255,0,255],
maroon:[128,0,0],
navy:[0,0,128],
olive:[128,128,0],
orange:[255,165,0],
pink:[255,192,203],
purple:[128,0,128],
violet:[128,0,128],
red:[255,0,0],
silver:[192,192,192],
white:[255,255,255],
yellow:[255,255,0]
};
function extractColor(element) {
var color, elem = element;
do {
color = elem.css("background-color").toLowerCase();
// keep going until we find an element that has color, or
// we hit the body
if (color != '' && color != 'transparent')
break;
elem = elem.parent();
} while (!$.nodeName(elem.get(0), "body"));
// catch Safari's way of signalling transparent
if (color == "rgba(0, 0, 0, 0)")
return "transparent";
return color;
}
// parse string, returns Color
function parseColor(str) {
var result;
// Look for rgb(num,num,num)
if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(str))
return new Color(parseInt(result[1], 10), parseInt(result[2], 10), parseInt(result[3], 10));
// Look for rgba(num,num,num,num)
if (result = /rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str))
return new Color(parseInt(result[1], 10), parseInt(result[2], 10), parseInt(result[3], 10), parseFloat(result[4]));
// Look for rgb(num%,num%,num%)
if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(str))
return new Color(parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55);
// Look for rgba(num%,num%,num%,num)
if (result = /rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str))
return new Color(parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55, parseFloat(result[4]));
// Look for #a0b1c2
if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(str))
return new Color(parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16));
// Look for #fff
if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(str))
return new Color(parseInt(result[1]+result[1], 16), parseInt(result[2]+result[2], 16), parseInt(result[3]+result[3], 16));
// Otherwise, we're most likely dealing with a named color
var name = $.trim(str).toLowerCase();
if (name == "transparent")
return new Color(255, 255, 255, 0);
else {
result = lookupColors[name];
return new Color(result[0], result[1], result[2]);
}
}
})(jQuery); })(jQuery);
/*
Flot plugin for selecting regions.
The plugin defines the following options:
selection: {
mode: null or "x" or "y" or "xy",
color: color
}
You enable selection support 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,
similarly for "y" mode. For "xy", the selection becomes a rectangle
where both ranges can be specified. "color" is color of the selection.
When selection support is enabled, a "plotselected" event will be emitted
on the DOM element you passed into the plot function. The event
handler gets one extra parameter with the ranges selected on the axes,
like this:
placeholder.bind("plotselected", function(event, ranges) {
alert("You selected " + ranges.xaxis.from + " to " + ranges.xaxis.to)
// similar for yaxis, secondary axes are in x2axis
// and y2axis if present
});
The "plotselected" event is only fired when the user has finished
making the selection. A "plotselecting" event is fired during the
process with the same parameters as the "plotselected" event, in case
you want to know what's happening while it's happening,
A "plotunselected" event with no arguments is emitted when the user
clicks the mouse to remove the selection.
The plugin allso adds the following methods to the plot object:
- setSelection(ranges, preventEvent)
Set the selection rectangle. The passed in ranges is on the same
form as returned in the "plotselected" event. If the selection
mode is "x", you should put in either an xaxis (or x2axis) object,
if the mode is "y" you need to put in an yaxis (or y2axis) object
and both xaxis/x2axis and yaxis/y2axis if the selection mode is
"xy", like this:
setSelection({ xaxis: { from: 0, to: 10 }, yaxis: { from: 40, to: 60 } });
setSelection will trigger the "plotselected" event when called. If
you don't want that to happen, e.g. if you're inside a
"plotselected" handler, pass true as the second parameter.
- clearSelection(preventEvent)
Clear the selection rectangle. Pass in true to avoid getting a
"plotunselected" event.
- getSelection()
Returns the current selection in the same format as the
"plotselected" event. If there's currently no selection, the
function returns null.
*/
(function ($) {
function init(plot) {
var selection = {
first: { x: -1, y: -1}, second: { x: -1, y: -1},
show: false,
active: false
};
// FIXME: The drag handling implemented here should be
// abstracted out, there's some similar code from a library in
// the navigation plugin, this should be massaged a bit to fit
// the Flot cases here better and reused. Doing this would
// make this plugin much slimmer.
var savedhandlers = {};
function onMouseMove(e) {
if (selection.active) {
plot.getPlaceholder().trigger("plotselecting", [ getSelection() ]);
updateSelection(e);
}
}
function onMouseDown(e) {
if (e.which != 1) // only accept left-click
return;
// cancel out any text selections
document.body.focus();
// prevent text selection and drag in old-school browsers
if (document.onselectstart !== undefined && savedhandlers.onselectstart == null) {
savedhandlers.onselectstart = document.onselectstart;
document.onselectstart = function () { return false; };
}
if (document.ondrag !== undefined && savedhandlers.ondrag == null) {
savedhandlers.ondrag = document.ondrag;
document.ondrag = function () { return false; };
}
setSelectionPos(selection.first, e);
selection.active = true;
$(document).one("mouseup", onMouseUp);
}
function onMouseUp(e) {
// revert drag stuff for old-school browsers
if (document.onselectstart !== undefined)
document.onselectstart = savedhandlers.onselectstart;
if (document.ondrag !== undefined)
document.ondrag = savedhandlers.ondrag;
// no more draggy-dee-drag
selection.active = false;
updateSelection(e);
if (selectionIsSane())
triggerSelectedEvent();
else {
// this counts as a clear
plot.getPlaceholder().trigger("plotunselected", [ ]);
plot.getPlaceholder().trigger("plotselecting", [ null ]);
}
return false;
}
function getSelection() {
if (!selectionIsSane())
return null;
var x1 = Math.min(selection.first.x, selection.second.x),
x2 = Math.max(selection.first.x, selection.second.x),
y1 = Math.max(selection.first.y, selection.second.y),
y2 = Math.min(selection.first.y, selection.second.y);
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;
}
function triggerSelectedEvent() {
var r = getSelection();
plot.getPlaceholder().trigger("plotselected", [ r ]);
// backwards-compat stuff, to be removed in future
var axes = plot.getAxes();
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 } ]);
}
function clamp(min, value, max) {
return value < min? min: (value > max? max: value);
}
function setSelectionPos(pos, e) {
var o = plot.getOptions();
var offset = plot.getPlaceholder().offset();
var plotOffset = plot.getPlotOffset();
pos.x = clamp(0, e.pageX - offset.left - plotOffset.left, plot.width());
pos.y = clamp(0, e.pageY - offset.top - plotOffset.top, plot.height());
if (o.selection.mode == "y")
pos.x = pos == selection.first? 0: plot.width();
if (o.selection.mode == "x")
pos.y = pos == selection.first? 0: plot.height();
}
function updateSelection(pos) {
if (pos.pageX == null)
return;
setSelectionPos(selection.second, pos);
if (selectionIsSane()) {
selection.show = true;
plot.triggerRedrawOverlay();
}
else
clearSelection(true);
}
function clearSelection(preventEvent) {
if (selection.show) {
selection.show = false;
plot.triggerRedrawOverlay();
if (!preventEvent)
plot.getPlaceholder().trigger("plotunselected", [ ]);
}
}
function setSelection(ranges, preventEvent) {
var axis, range, axes = plot.getAxes();
var o = plot.getOptions();
if (o.selection.mode == "y") {
selection.first.x = 0;
selection.second.x = plot.width();
}
else {
axis = ranges["xaxis"]? axes["xaxis"]: (ranges["x2axis"]? axes["x2axis"]: axes["xaxis"]);
range = ranges["xaxis"] || ranges["x2axis"] || { from:ranges["x1"], to:ranges["x2"] }
selection.first.x = axis.p2c(Math.min(range.from, range.to));
selection.second.x = axis.p2c(Math.max(range.from, range.to));
}
if (o.selection.mode == "x") {
selection.first.y = 0;
selection.second.y = plot.height();
}
else {
axis = ranges["yaxis"]? axes["yaxis"]: (ranges["y2axis"]? axes["y2axis"]: axes["yaxis"]);
range = ranges["yaxis"] || ranges["y2axis"] || { from:ranges["y1"], to:ranges["y2"] }
selection.first.y = axis.p2c(Math.min(range.from, range.to));
selection.second.y = axis.p2c(Math.max(range.from, range.to));
}
selection.show = true;
plot.triggerRedrawOverlay();
if (!preventEvent)
triggerSelectedEvent();
}
function selectionIsSane() {
var minSize = 5;
return Math.abs(selection.second.x - selection.first.x) >= minSize &&
Math.abs(selection.second.y - selection.first.y) >= minSize;
}
plot.clearSelection = clearSelection;
plot.setSelection = setSelection;
plot.getSelection = getSelection;
plot.hooks.bindEvents.push(function(plot, eventHolder) {
var o = plot.getOptions();
if (o.selection.mode != null)
eventHolder.mousemove(onMouseMove);
if (o.selection.mode != null)
eventHolder.mousedown(onMouseDown);
});
plot.hooks.drawOverlay.push(function (plot, ctx) {
// draw selection
if (selection.show && selectionIsSane()) {
var plotOffset = plot.getPlotOffset();
var o = plot.getOptions();
ctx.save();
ctx.translate(plotOffset.left, plotOffset.top);
var c = $.color.parse(o.selection.color);
ctx.strokeStyle = c.scale('a', 0.8).toString();
ctx.lineWidth = 1;
ctx.lineJoin = "round";
ctx.fillStyle = c.scale('a', 0.4).toString();
var x = Math.min(selection.first.x, selection.second.x),
y = Math.min(selection.first.y, selection.second.y),
w = Math.abs(selection.second.x - selection.first.x),
h = Math.abs(selection.second.y - selection.first.y);
ctx.fillRect(x, y, w, h);
ctx.strokeRect(x, y, w, h);
ctx.restore();
}
});
}
$.plot.plugins.push({
init: init,
options: {
selection: {
mode: null, // one of null, "x", "y" or "xy"
color: "#e8cfac"
}
},
name: 'selection',
version: '1.0'
});
})(jQuery);
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