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