Index: trunk/extensions/SlippyMap/SlippyMap.php |
— | — | @@ -59,17 +59,15 @@ |
60 | 60 | $wgAutoloadClasses['SlippyMap'] = $dir . 'SlippyMap.class.php'; |
61 | 61 | $wgExtensionMessagesFiles['SlippyMap'] = $dir . 'SlippyMap.i18n.php'; |
62 | 62 | |
63 | | -# Bump this when updating OpenStreetMap.js to help update caches |
64 | | -$wgSlippyMapVersion = 1; |
65 | | - |
66 | 63 | function wfslippymap() { |
67 | | - global $wgParser, $wgMapOfServiceUrl; |
| 64 | + global $wgParser, $wgHooks, $wgMapOfServiceUrl; |
68 | 65 | # register the extension with the WikiText parser |
69 | 66 | # the first parameter is the name of the new tag. |
70 | 67 | # In this case it defines the tag <slippymap> ... </slippymap> |
71 | 68 | # the second parameter is the callback function for |
72 | 69 | # processing the text between the tags |
73 | 70 | $wgParser->setHook( 'slippymap', array( 'SlippyMap', 'parse' ) ); |
| 71 | + $wgHooks['ParserAfterTidy'][] = 'SlippyMap::ParserAfterTidy'; |
74 | 72 | $wgMapOfServiceUrl = "http://osm-tah-cache.firefishy.com/~ojw/MapOf/?"; |
75 | 73 | return true; |
76 | 74 | } |
Index: trunk/extensions/SlippyMap/SlippyMap.class.php |
— | — | @@ -37,12 +37,18 @@ |
38 | 38 | # @addtogroup Extensions |
39 | 39 | # |
40 | 40 | |
| 41 | +# Evil hack as documented at |
| 42 | +# http://www.mediawiki.org/wiki/Manual:Tag_extensions#How_can_I_avoid_modification_of_my_extension.27s_HTML_output.3F |
| 43 | +# This is here so that random <p> and <pre> tags aren't added to the inline JavaScript output |
| 44 | +$SlippyMapMarkerList = array( ); |
| 45 | + |
| 46 | +# The number of Slippy Maps we have had thus far, to get unique JavaScript variables |
| 47 | +$SlippyMapCounter = 1; |
| 48 | + |
41 | 49 | class SlippyMap { |
42 | | - |
43 | 50 | # The callback function for converting the input text to HTML output |
44 | 51 | static function parse( $input, $argv ) { |
45 | | - global $wgScriptPath, $wgMapOfServiceUrl, $wgSlippyMapVersion; |
46 | | - |
| 52 | + global $SlippyMapMarkerList, $SlippyMapCounter; |
47 | 53 | wfLoadExtensionMessages( 'SlippyMap' ); |
48 | 54 | |
49 | 55 | // Support old style parameters from $input |
— | — | @@ -132,6 +138,19 @@ |
133 | 139 | $error = 'slippymap tag contents. Were you trying to input KML? KML support ' . |
134 | 140 | 'is disabled pending discussions about wiki syntax'; |
135 | 141 | $showkml = false; |
| 142 | +// KML code: |
| 143 | +// if ( $showkml ) { |
| 144 | +// $input = str_replace( array( '%', "\n" , "'" , '"' , '<' , '>' , ' ' ), |
| 145 | +// array( '%25', '%0A', '%27', '%22', '%3C', '%3E', '%20' ), $input ); |
| 146 | +// $output .= 'var vector = new OpenLayers.Layer.Vector("Vector Layer"); ' . |
| 147 | +// ' map.addLayer(vector); ' . |
| 148 | +// ' kml = new OpenLayers.Format.KML( { "internalProjection": map.baseLayer.projection, ' . |
| 149 | +// ' "externalProjection": epsg4326, ' . |
| 150 | +// ' "extractStyles": true, ' . |
| 151 | +// ' "extractAttributes": true } ); ' . |
| 152 | +// " features = kml.read(unescape('$input')); " . |
| 153 | +// ' vector.addFeatures( features ); '; |
| 154 | +// } |
136 | 155 | } else { |
137 | 156 | $showkml = false; |
138 | 157 | } |
— | — | @@ -184,11 +203,11 @@ |
185 | 204 | $layer = strtolower( $layer ); |
186 | 205 | $layerObjectDef = ''; |
187 | 206 | if ( $layer == 'osmarender' ) { |
188 | | - $layerObjectDef = 'OpenLayers.Layer.OSM.Osmarender("Osmarender"); '; |
| 207 | + $layerObjectDef = 'OpenLayers.Layer.OSM.Osmarender("Osmarender");'; |
189 | 208 | } elseif ( $layer == 'mapnik' ) { |
190 | | - $layerObjectDef = 'OpenLayers.Layer.OSM.Mapnik("Mapnik"); '; |
| 209 | + $layerObjectDef = 'OpenLayers.Layer.OSM.Mapnik("Mapnik");'; |
191 | 210 | } elseif ( $layer == 'maplint' ) { |
192 | | - $layerObjectDef = 'OpenLayers.Layer.OSM.Maplint("Maplint"); '; |
| 211 | + $layerObjectDef = 'OpenLayers.Layer.OSM.Maplint("Maplint");'; |
193 | 212 | } else { |
194 | 213 | $error = wfMsg( 'slippymap_invalidlayer', htmlspecialchars( $layer ) ); |
195 | 214 | } |
— | — | @@ -198,112 +217,159 @@ |
199 | 218 | $output = ''; |
200 | 219 | $output .= "<span class=\"error\">" . wfMsg( 'slippymap_maperror' ) . ' ' . $error . "</span><br />"; |
201 | 220 | $output .= htmlspecialchars( $input ); |
| 221 | + return $output; |
202 | 222 | } else { |
203 | | - // HTML output for the slippy map. |
204 | | - // Note that this must all be output on one line (no linefeeds) |
205 | | - // otherwise MediaWiki adds <BR> tags, which is bad in the middle of a block of javascript. |
206 | | - // There are other ways of fixing this, but not for MediaWiki v4 |
207 | | - // (See http://www.mediawiki.org/wiki/Manual:Tag_extensions#How_can_I_avoid_modification_of_my_extension.27s_HTML_output.3F) |
| 223 | + $output = self::makeSlippyMapHTMLandJS($lon, $lat, $zoom, $height, $width, $layerObjectDef, $marker, $SlippyMapCounter++); |
208 | 224 | |
209 | | - $output = '<!-- slippy map -->'; |
| 225 | + $markercount = count($SlippyMapMarkerList); |
| 226 | + $pMarker = "SlippyMap-marker".$markercount."-SlippyMap"; |
| 227 | + $SlippyMapMarkerList[$markercount] = $output; |
| 228 | + return $pMarker; |
| 229 | + } |
| 230 | + } |
210 | 231 | |
211 | | - // This inline stylesheet defines how the two extra buttons look, and where they are positioned. |
212 | | - $output .= "<style> .buttonsPanel div { float:left; display:block; position:relative; left:50px; margin-left:3px; margin-top:7px; width:36px; height:19px; }</style>\n"; |
213 | | - $output .= "<style> .buttonsPanel .getWikiCodeButtonItemInactive { width:36px; height:19px; background-image:url('" . $wgScriptPath . "/extensions/SlippyMap/wikicode-button.png'); }</style>\n"; |
214 | | - $output .= "<style> .buttonsPanel .resetButtonItemInactive { width:36px; height:19px; background-image:url('" . $wgScriptPath . "/extensions/SlippyMap/reset-button.png'); }</style>\n"; |
| 232 | + static function makeSlippyMapHTMLandJS($lon, $lat, $zoom, $height, $width, $layerObjectDef, $marker, $unique) { |
| 233 | + global $wgScriptPath, $wgMapOfServiceUrl; |
| 234 | + // HTML output for the slippy map. |
| 235 | + // Note that this must all be output on one line (no linefeeds) |
| 236 | + // otherwise MediaWiki adds <BR> tags, which is bad in the middle of a block of javascript. |
| 237 | + // There are other ways of fixing this, but not for MediaWiki v4 |
| 238 | + // (See http://www.mediawiki.org/wiki/Manual:Tag_extensions#How_can_I_avoid_modification_of_my_extension.27s_HTML_output.3F) |
215 | 239 | |
216 | | - $output .= "<!-- bring in the OpenLayers javascript library -->"; |
217 | | - $output .= "<script src=\"http://openlayers.org/api/OpenLayers.js\"></script> "; |
| 240 | + $slippymap_code_marker = ''; |
| 241 | + if ( $marker ) { |
| 242 | + $slippymap_code_marker = <<<EOT |
| 243 | +var markers${unique} = new OpenLayers.Layer.Markers( "Markers" ); |
| 244 | +map${unique}.addLayer(markers${unique}); |
| 245 | +var size${unique} = new OpenLayers.Size(20,34); |
| 246 | +var offset${unique} = new OpenLayers.Pixel(-(size${unique}.w/2), -size${unique}.h); |
| 247 | +var icon${unique} = new OpenLayers.Icon('http://boston.openguides.org/markers/YELLOW.png', size${unique},offset); |
| 248 | +markers${unique}.addMarker(new OpenLayers.Marker( lonLat${unique}, icon${unique} )); |
| 249 | +EOT; |
| 250 | + } |
218 | 251 | |
219 | | - $output .= "<!-- bring in the OpenStreetMap OpenLayers layers. "; |
220 | | - $output .= " Using this hosted file will make sure we are kept up "; |
221 | | - $output .= " to date with any necessary changes --> "; |
222 | | - $output .= "<script src=\"http://openstreetmap.org/openlayers/OpenStreetMap.js\"></script> "; |
| 252 | + $slippymap_code_escaped = Xml::escapeJsString( wfMsg( 'slippymap_code' ) ); |
| 253 | + $slippymap_button_code = Xml::escapeJsString( wfMsg( 'slippymap_button_code' ) ); |
| 254 | + $slippymap_resetview = Xml::escapeJsString( wfMsg( 'slippymap_resetview' ) ); |
223 | 255 | |
224 | | - $output .= '<script type="text/javascript">'; |
| 256 | + $slippymap_zoom_snippet = ''; |
| 257 | + if ( $height > 320 ) { |
| 258 | + // Add the zoom bar control, except if the map is only little |
| 259 | + $slippymap_zoom_snippet = 'new OpenLayers.Control.PanZoomBar(),'; |
| 260 | + } else if ( $height > 140 ) { |
| 261 | + $slippymap_zoom_snippet = 'new OpenLayers.Control.PanZoom(),'; |
| 262 | + } |
225 | 263 | |
226 | | - $output .= "var lon= ${lon}; var lat= ${lat}; var zoom= ${zoom}; var lonLat;"; |
| 264 | + $output = <<<EOT |
| 265 | +<!-- Slippy Map --> |
227 | 266 | |
228 | | - $output .= 'var map; '; |
| 267 | +<!-- This inline stylesheet defines how the two extra buttons look, and where they are positioned. --> |
| 268 | +<style> .buttonsPanel div { float:left; display:block; position:relative; left:50px; margin-left:3px; margin-top:7px; width:36px; height:19px; }</style> |
| 269 | +<style> .buttonsPanel .getWikiCodeButtonItemInactive { width:36px; height:19px; background-image:url('" . $wgScriptPath . "/extensions/SlippyMap/wikicode-button.png'); }</style> |
| 270 | +<style> .buttonsPanel .resetButtonItemInactive { width:36px; height:19px; background-image:url('" . $wgScriptPath . "/extensions/SlippyMap/reset-button.png'); }</style> |
229 | 271 | |
230 | | - $output .= 'addOnloadHook( slippymap_init ); '; |
| 272 | +<!-- bring in the OpenLayers javascript library --> |
| 273 | +<script src="http://openlayers.org/api/OpenLayers.js"></script> |
231 | 274 | |
232 | | - $output .= 'function slippymap_resetPosition() {'; |
233 | | - $output .= ' map.setCenter(lonLat, zoom);'; |
234 | | - $output .= '}'; |
| 275 | +<!-- bring in the OpenStreetMap OpenLayers layers. |
| 276 | + Using this hosted file will make sure we are kept up |
| 277 | + to date with any necessary changes --> |
| 278 | +<script src="http://openstreetmap.org/openlayers/OpenStreetMap.js"></script> |
235 | 279 | |
236 | | - $output .= 'function slippymap_getWikicode() {'; |
237 | | - $output .= ' LL = map.getCenter().transform(map.getProjectionObject(), new OpenLayers.Projection("EPSG:4326"));'; |
238 | | - $output .= ' Z = map.getZoom(); '; |
239 | | - $output .= ' size = map.getSize();'; |
| 280 | +<script type="text/javascript"> |
| 281 | + var lon${unique} = ${lon}; |
| 282 | + var lat${unique} = ${lat}; |
| 283 | + var zoom${unique} = ${zoom}; |
240 | 284 | |
241 | | - $output .= ' prompt( "' . wfMsg( 'slippymap_code' ) . '", "<slippymap h="+size.h+" w="+size.w+" z="+Z+" lat="+LL.lat+" lon="+LL.lon+" layer=mapnik marker=1></slippymap>" ); '; |
242 | | - $output .= '}'; |
| 285 | + var lonLat${unique}; |
| 286 | + var map${unique}; |
243 | 287 | |
244 | | - $output .= 'function slippymap_init() { '; |
245 | | - $output .= ' map = new OpenLayers.Map("map", { '; |
246 | | - $output .= ' controls:[ '; |
247 | | - $output .= ' new OpenLayers.Control.Navigation(), '; |
| 288 | + addOnloadHook( slippymap_init ); |
248 | 289 | |
249 | | - if ( $height > 320 ) { |
250 | | - // Add the zoom bar control, except if the map is only little |
251 | | - $output .= ' new OpenLayers.Control.PanZoomBar(),'; |
252 | | - } else if ( $height > 140 ) { |
253 | | - $output .= ' new OpenLayers.Control.PanZoom(),'; |
254 | | - } |
| 290 | + function slippymap_resetPosition() { |
| 291 | + map${unique}.setCenter(lonLat${unique}, zoom${unique}); |
| 292 | + } |
255 | 293 | |
256 | | - $output .= ' new OpenLayers.Control.Attribution()], '; |
257 | | - $output .= ' maxExtent: new OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34), '; |
258 | | - $output .= ' maxResolution:156543.0399, units:\'meters\', projection: "EPSG:900913"} ); '; |
| 294 | + function slippymap_getWikicode() { |
| 295 | + LL = map${unique}.getCenter().transform(map${unique}.getProjectionObject(), new OpenLayers.Projection("EPSG:4326")); |
| 296 | + Z = map${unique}.getZoom(); |
| 297 | + size = map${unique}.getSize(); |
| 298 | + prompt( |
| 299 | + "${slippymap_code_escaped}", |
| 300 | + "<slippymap h=" + size.h + " w=" + size.w + " z=" + Z + " lat=" + LL.lat + " lon=" + LL.lon + " layer=mapnik marker=1 />" |
| 301 | + ); |
| 302 | + } |
259 | 303 | |
260 | | - $output .= ' layer = new ' . $layerObjectDef; |
| 304 | + function slippymap_init() { |
| 305 | + // FIXME: Replace with OpenLayers.Layer.OSM?: http://trac.openlayers.org/changeset/9240 |
| 306 | + map${unique} = new OpenLayers.Map("map${unique}", { |
| 307 | + controls:[ |
| 308 | + new OpenLayers.Control.Navigation(), |
| 309 | + $slippymap_zoom_snippet |
| 310 | + new OpenLayers.Control.Attribution() |
| 311 | + ], |
| 312 | + maxExtent: new OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34), |
| 313 | + maxResolution:156543.0399, |
| 314 | + units: 'meters', |
| 315 | + projection: "EPSG:900913" |
| 316 | + }); |
261 | 317 | |
262 | | - $output .= ' map.addLayer(layer); '; |
| 318 | + layer = new ${layerObjectDef}; |
| 319 | + map${unique}.addLayer(layer); |
| 320 | + epsg4326 = new OpenLayers.Projection("EPSG:4326"); |
| 321 | + lonLat${unique} = new OpenLayers.LonLat(lon${unique}, lat${unique}).transform( epsg4326, map${unique}.getProjectionObject() ); |
263 | 322 | |
264 | | - $output .= ' epsg4326 = new OpenLayers.Projection("EPSG:4326"); '; |
265 | | - $output .= ' lonLat = new OpenLayers.LonLat(lon, lat).transform( epsg4326, map.getProjectionObject()); '; |
| 323 | + $slippymap_code_marker |
266 | 324 | |
267 | | - if ( $marker ) { |
268 | | - $output .= 'var markers = new OpenLayers.Layer.Markers( "Markers" ); ' . |
269 | | - ' map.addLayer(markers); ' . |
270 | | - ' var size = new OpenLayers.Size(20,34); ' . |
271 | | - ' var offset = new OpenLayers.Pixel(-(size.w/2), -size.h); ' . |
272 | | - " var icon = new OpenLayers.Icon('http://boston.openguides.org/markers/YELLOW.png',size,offset);" . |
273 | | - ' markers.addMarker(new OpenLayers.Marker( lonLat,icon)); '; |
274 | | - } |
| 325 | + map${unique}.setCenter(lonLat${unique}, zoom${unique}); |
275 | 326 | |
276 | | - if ( $showkml ) { |
277 | | - $input = str_replace( array( '%', "\n" , "'" , '"' , '<' , '>' , ' ' ), |
278 | | - array( '%25', '%0A', '%27', '%22', '%3C', '%3E', '%20' ), $input ); |
279 | | - $output .= 'var vector = new OpenLayers.Layer.Vector("Vector Layer"); ' . |
280 | | - ' map.addLayer(vector); ' . |
281 | | - ' kml = new OpenLayers.Format.KML( { "internalProjection": map.baseLayer.projection, ' . |
282 | | - ' "externalProjection": epsg4326, ' . |
283 | | - ' "extractStyles": true, ' . |
284 | | - ' "extractAttributes": true } ); ' . |
285 | | - " features = kml.read(unescape('$input')); " . |
286 | | - ' vector.addFeatures( features ); '; |
287 | | - } |
| 327 | + var getWikiCodeButton = new OpenLayers.Control.Button({ |
| 328 | + title: "${slippymap_button_code}", |
| 329 | + displayClass: "getWikiCodeButton", |
| 330 | + trigger: slippymap_getWikicode |
| 331 | + }); |
288 | 332 | |
289 | | - $output .= ' map.setCenter (lonLat, zoom); '; |
290 | | - $output .= ' var getWikiCodeButton = new OpenLayers.Control.Button({title: "' . wfMsg( 'slippymap_button_code' ) . '", displayClass: "getWikiCodeButton", trigger: slippymap_getWikicode}); '; |
291 | | - $output .= ' var resetButton = new OpenLayers.Control.Button({title: "' . wfMsg( 'slippymap_resetview' ) . '", displayClass: "resetButton", trigger: slippymap_resetPosition}); '; |
292 | | - $output .= ' var panel = new OpenLayers.Control.Panel( { displayClass: "buttonsPanel"}); '; |
293 | | - $output .= ' panel.addControls([getWikiCodeButton, resetButton]); '; |
294 | | - $output .= ' map.addControl(panel); '; |
295 | | - $output .= '} '; |
| 333 | + var resetButton = new OpenLayers.Control.Button({ |
| 334 | + title: "${slippymap_resetview}", |
| 335 | + displayClass: "resetButton", |
| 336 | + trigger: slippymap_resetPosition |
| 337 | + }); |
296 | 338 | |
| 339 | + var panel${unique} = new OpenLayers.Control.Panel( { displayClass: "buttonsPanel" } ); |
| 340 | + panel${unique}.addControls([getWikiCodeButton, resetButton]); |
| 341 | + map${unique}.addControl(panel${unique}); |
| 342 | + } |
| 343 | +</script> |
297 | 344 | |
298 | | - $output .= "</script> "; |
| 345 | +<div style="width: {$width}px; height:{$height}px; border-style:solid; border-width:1px; border-color:lightgrey;" id="map${unique}"> |
| 346 | +<noscript> |
| 347 | + <a href="http://www.openstreetmap.org/?lat=${lat}&lon=${lon}&zoom=${zoom}" title="See this map on OpenStreetMap.org" style="text-decoration:none"> |
| 348 | + <img |
| 349 | + src="${wgMapOfServiceUrl}lat=${lat}&long=${lon}&z=${zoom}&w=${width}&h=${height}&format=jpeg" |
| 350 | + width="${width}" |
| 351 | + height="${height}" |
| 352 | + border="0" |
| 353 | + alt="Slippy Map" /> |
| 354 | + <br /> |
| 355 | + </a> |
| 356 | +</noscript> |
| 357 | +</div> |
| 358 | +EOT; |
299 | 359 | |
300 | | - $output .= "<div style=\"width: {$width}px; height:{$height}px; border-style:solid; border-width:1px; border-color:lightgrey;\" id=\"map\">"; |
301 | | - $output .= "<noscript><a href=\"http://www.openstreetmap.org/?lat=$lat&lon=$lon&zoom=$zoom\" title=\"See this map on OpenStreetMap.org\" style=\"text-decoration:none\">"; |
302 | | - $output .= "<img src=\"" . $wgMapOfServiceUrl . "lat=${lat}&long=${lon}&z=${zoom}&w=${width}&h=${height}&format=jpeg\" width=\"${width}\" height=\"${height}\" border=\"0\" alt=\"Slippy Map\"><br />"; |
303 | | - $output .= '</a></noscript>'; |
304 | | - $output .= '</div>'; |
| 360 | + return $output; |
| 361 | + } |
305 | 362 | |
306 | | - if ( sizeof( $oldStyleParamStrings ) > 2 ) $output .= '<div style="font-size:0.8em;"><i>please change to <a href="http://wiki.openstreetmap.org/index.php/Slippy_Map_MediaWiki_Extension">new syntax</a></i></div>'; |
| 363 | + // Hack, see beginning of file for why |
| 364 | + static function ParserAfterTidy(&$parser, &$text) { |
| 365 | + global $SlippyMapMarkerList; |
| 366 | + $keys = array(); |
| 367 | + $marker_count = count($SlippyMapMarkerList); |
| 368 | + |
| 369 | + for ($i = 0; $i < $marker_count; $i++) { |
| 370 | + $keys[] = 'SlippyMap-marker' . $i . '-SlippyMap'; |
307 | 371 | } |
308 | | - return $output; |
| 372 | + |
| 373 | + $text = str_replace($keys, $SlippyMapMarkerList, $text); |
| 374 | + return true; |
309 | 375 | } |
310 | 376 | } |