| 1 |
Writing plugins |
| 2 |
--------------- |
| 3 |
|
| 4 |
All you need to do to make a new plugin is creating an init function |
| 5 |
and a set of options (if needed), stuffing it into an object and |
| 6 |
putting it in the $.plot.plugins array. For example: |
| 7 |
|
| 8 |
function myCoolPluginInit(plot) { |
| 9 |
plot.coolstring = "Hello!"; |
| 10 |
}; |
| 11 |
|
| 12 |
$.plot.plugins.push({ init: myCoolPluginInit, options: { ... } }); |
| 13 |
|
| 14 |
// if $.plot is called, it will return a plot object with the |
| 15 |
// attribute "coolstring" |
| 16 |
|
| 17 |
Now, given that the plugin might run in many different places, it's |
| 18 |
a good idea to avoid leaking names. The usual trick here is wrap the |
| 19 |
above lines in an anonymous function which is called immediately, like |
| 20 |
this: (function () { inner code ... })(). To make it even more robust |
| 21 |
in case $ is not bound to jQuery but some other Javascript library, we |
| 22 |
can write it as |
| 23 |
|
| 24 |
(function ($) { |
| 25 |
// plugin definition |
| 26 |
// ... |
| 27 |
})(jQuery); |
| 28 |
|
| 29 |
There's a complete example below, but you should also check out the |
| 30 |
plugins bundled with Flot. |
| 31 |
|
| 32 |
|
| 33 |
Complete example |
| 34 |
---------------- |
| 35 |
|
| 36 |
Here is a simple debug plugin which alerts each of the series in the |
| 37 |
plot. It has a single option that control whether it is enabled and |
| 38 |
how much info to output: |
| 39 |
|
| 40 |
(function ($) { |
| 41 |
function init(plot) { |
| 42 |
var debugLevel = 1; |
| 43 |
|
| 44 |
function checkDebugEnabled(plot, options) { |
| 45 |
if (options.debug) { |
| 46 |
debugLevel = options.debug; |
| 47 |
|
| 48 |
plot.hooks.processDatapoints.push(alertSeries); |
| 49 |
} |
| 50 |
} |
| 51 |
|
| 52 |
function alertSeries(plot, series, datapoints) { |
| 53 |
var msg = "series " + series.label; |
| 54 |
if (debugLevel > 1) |
| 55 |
msg += " with " + series.data.length + " points"; |
| 56 |
alert(msg); |
| 57 |
} |
| 58 |
|
| 59 |
plot.hooks.processOptions.push(checkDebugEnabled); |
| 60 |
} |
| 61 |
|
| 62 |
var options = { debug: 0 }; |
| 63 |
|
| 64 |
$.plot.plugins.push({ |
| 65 |
init: init, |
| 66 |
options: options, |
| 67 |
name: "simpledebug", |
| 68 |
version: "0.1" |
| 69 |
}); |
| 70 |
})(jQuery); |
| 71 |
|
| 72 |
We also define "name" and "version". It's not used by Flot, but might |
| 73 |
be helpful for other plugins in resolving dependencies. |
| 74 |
|
| 75 |
Put the above in a file named "jquery.flot.debug.js", include it in an |
| 76 |
HTML page and then it can be used with: |
| 77 |
|
| 78 |
$.plot($("#placeholder"), [...], { debug: 2 }); |
| 79 |
|
| 80 |
This simple plugin illustrates a couple of points: |
| 81 |
|
| 82 |
- It uses the anonymous function trick to avoid name pollution. |
| 83 |
- It can be enabled/disabled through an option. |
| 84 |
- Variables in the init function can be used to store plot-specific |
| 85 |
state between the hooks. |
| 86 |
|
| 87 |
The two last points are important because there may be multiple plots |
| 88 |
on the same page, and you'd want to make sure they are not mixed up. |
| 89 |
|
| 90 |
|
| 91 |
Shutting down a plugin |
| 92 |
---------------------- |
| 93 |
|
| 94 |
Each plot object has a shutdown hook which is run when plot.shutdown() |
| 95 |
is called. This usually mostly happens in case another plot is made on |
| 96 |
top of an existing one. |
| 97 |
|
| 98 |
The purpose of the hook is to give you a chance to unbind any event |
| 99 |
handlers you've registered and remove any extra DOM things you've |
| 100 |
inserted. |
| 101 |
|
| 102 |
The problem with event handlers is that you can have registered a |
| 103 |
handler which is run in some point in the future, e.g. with |
| 104 |
setTimeout(). Meanwhile, the plot may have been shutdown and removed, |
| 105 |
but because your event handler is still referencing it, it can't be |
| 106 |
garbage collected yet, and worse, if your handler eventually runs, it |
| 107 |
may overwrite stuff on a completely different plot. |
| 108 |
|
| 109 |
|
| 110 |
Some hints on the options |
| 111 |
------------------------- |
| 112 |
|
| 113 |
Plugins should always support appropriate options to enable/disable |
| 114 |
them because the plugin user may have several plots on the same page |
| 115 |
where only one should use the plugin. In most cases it's probably a |
| 116 |
good idea if the plugin is turned off rather than on per default, just |
| 117 |
like most of the powerful features in Flot. |
| 118 |
|
| 119 |
If the plugin needs options that are specific to each series, like the |
| 120 |
points or lines options in core Flot, you can put them in "series" in |
| 121 |
the options object, e.g. |
| 122 |
|
| 123 |
var options = { |
| 124 |
series: { |
| 125 |
downsample: { |
| 126 |
algorithm: null, |
| 127 |
maxpoints: 1000 |
| 128 |
} |
| 129 |
} |
| 130 |
} |
| 131 |
|
| 132 |
Then they will be copied by Flot into each series, providing default |
| 133 |
values in case none are specified. |
| 134 |
|
| 135 |
Think hard and long about naming the options. These names are going to |
| 136 |
be public API, and code is going to depend on them if the plugin is |
| 137 |
successful. |
| 138 |
|