Index: trunk/extensions/Plotters/PlottersParser.php |
— | — | @@ -36,7 +36,7 @@ |
37 | 37 | // Parse arguments, set defaults, and do sanity checks |
38 | 38 | $this->argumentArray = array ( "renderer" => "plotkit", "preprocessors" => array(), "preprocessorarguments" => array(), |
39 | 39 | "script" => "", "scriptarguments" => array(), "datasep" => ",", "width" => "300", "height" => "300", "labels" => array(), |
40 | | - "helpers" => array() ); |
| 40 | + "helpers" => array(), "name" => "plot", "tableclass" => "wikitable" ); |
41 | 41 | if ( isset( $argv["renderer"] ) ) { |
42 | 42 | //TODO: limit this to supported renderers |
43 | 43 | $this->argumentArray["renderer"] = preg_replace( '/[^A-Z0-9]/i', '', $argv["renderer"] ); |
— | — | @@ -114,6 +114,14 @@ |
115 | 115 | $helper = preg_replace( '/[^A-Z0-9]/i', '', $helper ); |
116 | 116 | } |
117 | 117 | } |
| 118 | + if ( isset( $argv["name"] ) ) { |
| 119 | + // Sanitize names - alphanumerics only |
| 120 | + $this->argumentArray["name"] = preg_replace( '/[^A-Z0-9]/i', '', $argv["name"] ); |
| 121 | + } |
| 122 | + if ( isset( $argv["tableclass"] ) ) { |
| 123 | + // Sanitize tableclass - alphanumerics only |
| 124 | + $this->argumentArray["tableclass"] = preg_replace( '/[^A-Z0-9]/i', '', $argv["tableclass"] ); |
| 125 | + } |
118 | 126 | } |
119 | 127 | |
120 | 128 | function parseData( $input, $parser ) { |
Index: trunk/extensions/Plotters/Plotters.i18n.php |
— | — | @@ -28,6 +28,8 @@ |
29 | 29 | 'plotters-excessively-long-scriptname' => 'The script name is too long. Please define a script that is less than 255 characters.', |
30 | 30 | 'plotters-excessively-long-preprocessorname' => 'The preprocessor name is too long. Please define a preprocessor that is less than 255 characters.', |
31 | 31 | 'plotters-excessively-long-helpername' => 'The helper name is too long. Please define a helper that is less than 255 characters.', |
| 32 | + 'plotters-excessively-long-name' => 'The plot name is too long. Please define a plot name that is less than 255 characters.', |
| 33 | + 'plotters-excessively-long-tableclass' => 'The tableclass is too long. Please define a tableclass that is less than 255 characters.', |
32 | 34 | 'plotters-no-data' => 'No data was provided.', |
33 | 35 | 'plotters-invalid-renderer' => 'An invalid renderer was selected.', |
34 | 36 | 'plotters-errors' => '<b>Plotters error(s):</b>', |
Index: trunk/extensions/Plotters/PlottersClass.php |
— | — | @@ -51,6 +51,7 @@ |
52 | 52 | // Check to ensure scriptname is < 255 characters |
53 | 53 | $errors .= wfMsg( "plotters-excessively-long-scriptname" ) . "<br />"; |
54 | 54 | } |
| 55 | + |
55 | 56 | // Check preprocessors and helpers |
56 | 57 | foreach ( $this->argumentArray["preprocessors"] as $preprocessor ) { |
57 | 58 | if ( strlen( $preprocessor ) > 255 ) { |
— | — | @@ -62,6 +63,15 @@ |
63 | 64 | $errors .= wfMsg( "plotters-excessively-long-helpername" ) . "<br />"; |
64 | 65 | } |
65 | 66 | } |
| 67 | + |
| 68 | + if ( strlen( $this->argumentArray["name"] ) > 255 ) { |
| 69 | + $errors .= wfMsg( "plotters-excessively-long-name" ) . "<br />"; |
| 70 | + } |
| 71 | + |
| 72 | + if ( strlen( $this->argumentArray["tableclass"] ) > 255 ) { |
| 73 | + $errors .= wfMsg( "plotters-excessively-long-tableclass" ) . "<br />"; |
| 74 | + } |
| 75 | + |
66 | 76 | // Check for data |
67 | 77 | if ( count( $this->dataArray ) == 0 ) { |
68 | 78 | $errors .= wfMsg( "plotters-no-data" ) . "<br />"; |
— | — | @@ -107,19 +117,40 @@ |
108 | 118 | } |
109 | 119 | |
110 | 120 | function renderPlot() { |
111 | | - // TODO: allow user defined graph id |
112 | | - return '<div><canvas id="graph" height="' . $this->argumentArray["height"] . '" width="' . $this->argumentArray["width"] . '"></canvas></div>'; |
| 121 | + return '<div id="' . $this->argumentArray["name"] . '-div" style="display: none;"><canvas id="' . $this->argumentArray["name"] . '" height="' . $this->argumentArray["height"] . '" width="' . $this->argumentArray["width"] . '"></canvas></div>'; |
113 | 122 | } |
114 | 123 | |
115 | 124 | function renderFallback() { |
116 | 125 | // Return an html table of the data |
117 | | - return ''; |
| 126 | + $output = '<table id="' . $this->argumentArray["name"] . '-fallback" class="' . $this->argumentArray["tableclass"] . '">'; |
| 127 | + if ( count( $this->argumentArray["labels"] ) > 0 ) { |
| 128 | + $output .= "<tr>"; |
| 129 | + foreach ( $this->argumentArray["labels"] as $label ) { |
| 130 | + $output .= "<th>" . $label . "</th>"; |
| 131 | + } |
| 132 | + $output .= "</tr>"; |
| 133 | + } |
| 134 | + foreach ( $this->dataArray as $dataline ) { |
| 135 | + $output .= "<tr>"; |
| 136 | + foreach ( $dataline as $data ) { |
| 137 | + $output .= "<td>" . $data . "</td>"; |
| 138 | + } |
| 139 | + $output .= "</tr>"; |
| 140 | + } |
| 141 | + $output .= "</table>"; |
| 142 | + |
| 143 | + return $output; |
118 | 144 | } |
119 | 145 | |
120 | 146 | function renderJavascript() { |
| 147 | + $name = $this->argumentArray["name"]; |
| 148 | + |
121 | 149 | $output = '<script type="text/javascript">'; |
122 | | - // TODO: allow user defined graph id |
123 | | - $output .= 'function drawGraph() {'; |
| 150 | + |
| 151 | + $output .= 'document.getElementById("' . $this->argumentArray["name"] . '-fallback").style.display = "none";'; // hide fallback table |
| 152 | + $output .= 'document.getElementById("' . $this->argumentArray["name"] . '-div").style.display = "block";'; // show canvas |
| 153 | + |
| 154 | + $output .= 'function draw' . $this->argumentArray["name"] . '() {'; |
124 | 155 | $output .= 'var data = [];'; |
125 | 156 | |
126 | 157 | // Prepare data |
— | — | @@ -140,7 +171,7 @@ |
141 | 172 | |
142 | 173 | // Run preprocessors |
143 | 174 | foreach ( $this->argumentArray["preprocessors"] as $preprocessor ) { |
144 | | - $output .= 'plotter_' . $preprocessor . '_process( data, labels, '; |
| 175 | + $output .= 'plotter_' . $preprocessor . '_process( "' . $name . '", data, labels, '; |
145 | 176 | foreach ( $this->argumentArray["preprocessorarguments"] as $argument ) { |
146 | 177 | $output .= $argument . ', '; |
147 | 178 | } |
— | — | @@ -150,7 +181,7 @@ |
151 | 182 | } |
152 | 183 | |
153 | 184 | // Run script |
154 | | - $output .= 'plotter_' . $this->argumentArray["script"] . '_draw( data, labels, '; |
| 185 | + $output .= 'plotter_' . $this->argumentArray["script"] . '_draw( "' . $name . '", data, labels, '; |
155 | 186 | foreach ( $this->argumentArray["scriptarguments"] as $argument ) { |
156 | 187 | $output .= "'" . $argument . "'" . ", "; |
157 | 188 | } |
— | — | @@ -160,8 +191,7 @@ |
161 | 192 | $output .= "}"; |
162 | 193 | |
163 | 194 | // Add hook event |
164 | | - // TODO: allow user defined graph id |
165 | | - $output .= 'hookEvent("load", drawGraph);'; |
| 195 | + $output .= 'hookEvent("load", draw' . $this->argumentArray["name"] . ');'; |
166 | 196 | $output .= "</script>"; |
167 | 197 | |
168 | 198 | return $output; |
Index: trunk/extensions/Plotters/README |
— | — | @@ -1,31 +1,76 @@ |
2 | | -This extension allows users to create client side graphs (like pie, bar, etc) |
3 | | -from data using javascript. The javascript is created by sysops in the |
4 | | -MediaWiki namespace. Adding new scripts works like the Gadgets extension (as |
5 | | -this extension borrows heavily from Gadgets). |
| 2 | +This extension allows users to create client side graphs (like pie, bar, etc) from data using javascript. The javascript is created by sysops in the MediaWiki namespace. Adding new scripts works like the Gadgets extension (as this extension borrows heavily from Gadgets). |
6 | 3 | |
7 | | -Preprocessing scripts, and plotting scripts are available, and the javascript |
8 | | -function for each should be defined as follows: |
| 4 | +Preprocessing scripts, plotting scripts, and helpers are available, and the javascript function for each should be defined as follows: |
9 | 5 | |
10 | 6 | /* For preprocessing scripts */ |
11 | | -function plotter_<functionname>_process( data, labels, arg1, arg2, ... ) { |
12 | | - ... |
| 7 | +function plotter_<functionname>_process( name, data, labels, arguments ) { |
| 8 | + /* example preprocessor: */ |
| 9 | + for ( var i = 0; i < data.length; ++i ) { |
| 10 | + for ( var j = 1; j < data[i].length; ++j ) { |
| 11 | + data[i][j] = data[i][j] * 2; |
| 12 | + } |
| 13 | + } |
13 | 14 | } |
14 | 15 | |
15 | 16 | /* For plotting scripts */ |
16 | | -function plotter_<functionname>_draw( data, labels, arg1, arg2, ... ) { |
17 | | - ... |
| 17 | +function plotter_<functionname>_draw( name, data, labels, arguments ) { |
| 18 | + /* example plotkit script: */ |
| 19 | + var plotkitlabels = []; |
| 20 | + for ( var i = 0; i < labels.length; ++i ) { |
| 21 | + plotkitlabels[i] = { v:i, label:labels[i] }; |
| 22 | + } |
| 23 | + var options = { "xTicks": plotkitlabels }; |
| 24 | + var layout = new PlotKit.Layout("bar", options); |
| 25 | + layout.addDataset("data", data); |
| 26 | + layout.evaluate(); |
| 27 | + var canvas = MochiKit.DOM.getElement(name); |
| 28 | + var plotter = new PlotKit.SweetCanvasRenderer(canvas, layout, options); |
| 29 | + plotter.render(); |
18 | 30 | } |
19 | 31 | |
| 32 | +/* For helpers - this is javascript that is loaded, but not called |
| 33 | + by the plugin; they are for use in functions called by the plugin */ |
| 34 | +function plotter_<functionname>( <anything_you_want> ) { |
| 35 | + /* ... */ |
| 36 | +} |
| 37 | + |
20 | 38 | You can use these in a parser function like so: |
21 | 39 | |
22 | 40 | {{#plot: |
23 | | -|script=<functionname> |
| 41 | +|script=<scriptname> |
24 | 42 | |scriptarguments=arg1,arg2,... |
| 43 | +|preprocessors=<preprocessorname1>,<preprocessorname2>,... |
| 44 | +|preprocessorarguments=<preprocessor1argument1>,<preprocessor1argument2>,...:preprocessor2argument1>,<preprocessor2argument2>,...:...,... |
| 45 | +|helpers=<helpername1>,<helpername2>,... |
25 | 46 | |labels=label1,label2 |
26 | 47 | |data=1,2 |
27 | 48 | 2,4}} |
28 | 49 | |
29 | | -Currently, only PlotKit, and generic canvas drawing is supported; but other javascript plotting libraries |
30 | | -will be supported in the future. |
| 50 | +To specify multiple plots in a single article, you need to use the name argument; the default is name=plot; here is an example of multiple plots: |
31 | 51 | |
32 | | -This code is very alpha quality right now; many features may not work. |
| 52 | +{{#plot: |
| 53 | +|name=plot1 |
| 54 | +|script=<scriptname> |
| 55 | +|data=1,2}} |
| 56 | + |
| 57 | +{{#plot: |
| 58 | +|name=plot2 |
| 59 | +|script=<scriptname> |
| 60 | +|data=2,3}} |
| 61 | + |
| 62 | +If javascript is disabled, the extension will instead show a table. To specify the CSS class of the fallback table, use the tableclass argument; the default is tableclass=wikitable |
| 63 | + |
| 64 | +{{#plot: |
| 65 | +|script=<scriptname> |
| 66 | +|tableclass=sortable |
| 67 | +|data=0,1}} |
| 68 | + |
| 69 | +The height and width of the canvas can be changed with the width and height arguments; the defaults are width=300 height=300 |
| 70 | + |
| 71 | +To change the renderer, use the renderer argument. Currently, only PlotKit (renderer=plotkit), and generic canvas drawing (renderer=generic) is supported; but other javascript plotting libraries will be supported in the future; the default is renderer=plotkit. |
| 72 | + |
| 73 | +The data separator can be changed using the datasep argument; the default is datasep=, |
| 74 | + |
| 75 | +script, preprocessors, helpers, name, and tableclass arguments are alphanumeric only, and are limited to 255 characters per script/preprocessor/etc. |
| 76 | + |
| 77 | +This code is alpha quality right now; many features may not work. |