Index: trunk/extensions/SlippyMap/SlippyMap.i18n.php |
— | — | @@ -56,6 +56,8 @@ |
57 | 57 | 'slippymap_button_code' => 'Get wikicode', |
58 | 58 | 'slippymap_resetview' => 'Reset view', |
59 | 59 | 'slippymap_license' => 'OpenStreetMap - CC-BY-SA-2.0', # do not translate or duplicate this message to other languages |
| 60 | + 'slippymap_invalidmode' => "Invalid 'mode' value '$1'", |
| 61 | + 'slippymap_clicktoactivate' => 'Click to activate map' |
60 | 62 | ); |
61 | 63 | |
62 | 64 | /** Message documentation (Message documentation) |
Index: trunk/extensions/SlippyMap/SlippyMap.php |
— | — | @@ -1,74 +1,82 @@ |
2 | | -<?php |
3 | | -# OpenStreetMap SlippyMap - MediaWiki extension |
4 | | -# |
5 | | -# This defines what happens when <slippymap> tag is placed in the wikitext |
6 | | -# |
7 | | -# We show a map based on the lat/lon/zoom data passed in. This extension brings in |
8 | | -# the OpenLayers javascript, to show a slippy map. |
9 | | -# |
10 | | -# Usage example: |
11 | | -# <slippymap lat=51.485 lon=-0.15 z=11 w=300 h=200 layer=osmarender></slippymap> |
12 | | -# |
13 | | -# Tile images are not cached local to the wiki. |
14 | | -# To acheive this (remove the OSM dependency) you might set up a squid proxy, |
15 | | -# and modify the requests URLs here accordingly. |
16 | | -# |
17 | | -# This file should be placed in the mediawiki 'extensions' directory |
18 | | -# ...and then it needs to be 'included' within LocalSettings.php |
19 | | -# |
20 | | -# ################################################################################# |
21 | | -# |
22 | | -# Copyright 2008 Harry Wood, Jens Frank, Grant Slater, Raymond Spekking and others |
23 | | -# |
24 | | -# This program is free software; you can redistribute it and/or modify |
25 | | -# it under the terms of the GNU General Public License as published by |
26 | | -# the Free Software Foundation; either version 2 of the License, or |
27 | | -# (at your option) any later version. |
28 | | -# |
29 | | -# This program is distributed in the hope that it will be useful, |
30 | | -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
31 | | -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
32 | | -# GNU General Public License for more details. |
33 | | -# |
34 | | -# You should have received a copy of the GNU General Public License |
35 | | -# along with this program; if not, write to the Free Software |
36 | | -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
37 | | -# |
38 | | -# @addtogroup Extensions |
39 | | -# |
| 2 | +<?php |
| 3 | +/** |
| 4 | +* @file |
| 5 | +* |
| 6 | +* @section DESCRIPTION |
| 7 | +* |
| 8 | +* OpenStreetMap SlippyMap - MediaWiki extension |
| 9 | +* |
| 10 | +* This defines what happens when <slippymap> tag is placed in the wikitext |
| 11 | +* |
| 12 | +* We show a map based on the lat/lon/zoom data passed in. This extension brings in |
| 13 | +* the OpenLayers javascript, to show a slippy map. |
| 14 | +* |
| 15 | +* Usage example: |
| 16 | +* <slippymap lat=51.485 lon=-0.15 z=11 w=300 h=200 layer=osmarender></slippymap> |
| 17 | +* |
| 18 | +* Tile images are not cached local to the wiki. |
| 19 | +* To acheive this (remove the OSM dependency) you might set up a squid proxy, |
| 20 | +* and modify the requests URLs here accordingly. |
| 21 | +* |
| 22 | +* This file should be placed in the mediawiki 'extensions' directory |
| 23 | +* ...and then it needs to be 'included' within LocalSettings.php |
| 24 | +* |
| 25 | +* @section LICENSE |
| 26 | +* |
| 27 | +* Copyright 2008 Harry Wood, Jens Frank, Grant Slater, Raymond Spekking and others |
| 28 | +* |
| 29 | +* This program is free software; you can redistribute it and/or modify |
| 30 | +* it under the terms of the GNU General Public License as published by |
| 31 | +* the Free Software Foundation; either version 2 of the License, or |
| 32 | +* (at your option) any later version. |
| 33 | +* |
| 34 | +* This program is distributed in the hope that it will be useful, |
| 35 | +* but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 36 | +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 37 | +* GNU General Public License for more details. |
| 38 | +* |
| 39 | +* You should have received a copy of the GNU General Public License |
| 40 | +* along with this program; if not, write to the Free Software |
| 41 | +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 42 | +* |
| 43 | +*/ |
40 | 44 | |
41 | | - |
| 45 | +/** |
| 46 | + * Checks if the file is being executed within MediaWiki |
| 47 | + */ |
42 | 48 | if ( !defined( 'MEDIAWIKI' ) ) |
43 | | - die(); |
| 49 | + die(); |
44 | 50 | |
45 | | -if ( defined( 'MW_SUPPORTS_PARSERFIRSTCALLINIT' ) ) { |
46 | | - $wgHooks['ParserFirstCallInit'][] = 'wfslippymap'; |
47 | | -} else { |
48 | | - $wgExtensionFunctions[] = 'wfslippymap'; |
49 | | -} |
50 | 51 | |
| 52 | +/** |
| 53 | +* Property: Extension credits |
| 54 | +*/ |
51 | 55 | $wgExtensionCredits['parserhook'][] = array( |
52 | | - 'path' => __FILE__, |
53 | | - 'name' => 'OpenStreetMap Slippy Map', |
54 | | - 'author' => array( '[http://harrywood.co.uk Harry Wood]', 'Jens Frank' ), |
55 | | - 'url' => 'http://wiki.openstreetmap.org/index.php/Slippy_Map_MediaWiki_Extension', |
56 | | - 'description' => 'Allows the use of the <slippymap> tag to display an OpenLayers slippy map. Maps are from [http://openstreetmap.org openstreetmap.org]', |
57 | | - 'descriptionmsg' => 'slippymap_desc', |
| 56 | + 'name' => 'OpenStreetMap Slippy Map', |
| 57 | + 'author' => array( '[http://harrywood.co.uk Harry Wood]', 'Jens Frank' ), |
| 58 | + 'url' => 'http://wiki.openstreetmap.org/index.php/Slippy_Map_MediaWiki_Extension', |
| 59 | + 'description' => 'Allows the use of the <slippymap> tag to display an OpenLayers slippy map. Maps are from [http://openstreetmap.org openstreetmap.org]', |
| 60 | + 'descriptionmsg' => 'slippymap_desc', |
58 | 61 | ); |
59 | 62 | |
60 | 63 | $dir = dirname( __FILE__ ) . '/'; |
61 | | -$wgAutoloadClasses['SlippyMap'] = $dir . 'SlippyMap.class.php'; |
| 64 | + |
| 65 | +$wgMapModes = array( 'osm', 'satellite' ); |
| 66 | + |
| 67 | +$wgAutoLoadMaps = false; |
| 68 | + |
62 | 69 | $wgExtensionMessagesFiles['SlippyMap'] = $dir . 'SlippyMap.i18n.php'; |
| 70 | +$wgExtensionAliasesFiles['SlippyMap'] = $dir . 'SlippyMap.alias.php'; |
63 | 71 | |
64 | | -function wfslippymap() { |
65 | | - global $wgParser, $wgHooks, $wgMapOfServiceUrl; |
66 | | - # register the extension with the WikiText parser |
67 | | - # the first parameter is the name of the new tag. |
68 | | - # In this case it defines the tag <slippymap> ... </slippymap> |
69 | | - # the second parameter is the callback function for |
70 | | - # processing the text between the tags |
71 | | - $wgParser->setHook( 'slippymap', array( 'SlippyMap', 'parse' ) ); |
72 | | - $wgHooks['ParserAfterTidy'][] = 'SlippyMap::ParserAfterTidy'; |
73 | | - $wgMapOfServiceUrl = "http://osm-tah-cache.firefishy.com/~ojw/MapOf/?"; |
74 | | - return true; |
| 72 | +$wgAutoloadClasses['SlippyMapHooks'] = $dir . 'SlippyMap.hooks.php'; |
| 73 | +$wgAutoloadClasses['SlippyMap'] = $dir . 'SlippyMap.class.php'; |
| 74 | +$wgAutoloadClasses['WorldWind'] = $dir . 'SlippyMap.worldwind.php'; |
| 75 | + |
| 76 | +if ( defined( 'MW_SUPPORTS_PARSERFIRSTCALLINIT' ) ) { |
| 77 | + $wgHooks['ParserFirstCallInit'][] = 'SlippyMapHooks::onParserFirstCallInit'; |
| 78 | +} else { |
| 79 | + $wgExtensionFunctions[] = 'SlippyMapHooks::onParserFirstCallInit'; |
75 | 80 | } |
| 81 | + |
| 82 | +$wgHooks['ParserAfterTidy'][] = 'SlippyMapHooks::wfSlippyMapParserAfterTidy'; |
| 83 | + |
Index: trunk/extensions/SlippyMap/SlippyMap.css |
— | — | @@ -0,0 +1,61 @@ |
| 2 | +.mapframe { |
| 3 | + position:relative; |
| 4 | + padding:.7em; |
| 5 | + color:#191970; |
| 6 | + float:right; |
| 7 | + border:solid 1px #cccccc; |
| 8 | +} |
| 9 | + |
| 10 | +.map { |
| 11 | + position:relative; |
| 12 | + border:solid 1px #000000; |
| 13 | + float:right; |
| 14 | + clear:right; |
| 15 | + width: 100%; |
| 16 | +} |
| 17 | + |
| 18 | +.mapPreview { |
| 19 | + cursor: pointer; |
| 20 | + border: none; |
| 21 | +} |
| 22 | + |
| 23 | +.mapcaption { |
| 24 | + position:relative; |
| 25 | + clear:right; |
| 26 | + float:right; |
| 27 | + width: 100%; |
| 28 | +} |
| 29 | + |
| 30 | +/* |
| 31 | + * Force override of delay-loaded styles from openlayers/theme/default/style.css |
| 32 | + * TODO In the long run, we should probably create a MediaWiki theme |
| 33 | + * that contains customizations |
| 34 | + */ |
| 35 | +.olControlAttribution { |
| 36 | + right: 5px !important; |
| 37 | + bottom: 0px !important; |
| 38 | +} |
| 39 | + |
| 40 | +/* Custom wikiCode and reset buttons */ |
| 41 | +.buttonsPanel div { |
| 42 | + float:left; |
| 43 | + display:block; |
| 44 | + position:relative; |
| 45 | + left:50px; |
| 46 | + margin-left:3px; |
| 47 | + margin-top:7px; |
| 48 | + width:36px; |
| 49 | + height:19px; |
| 50 | +} |
| 51 | + |
| 52 | +.buttonsPanel .getWikiCodeButtonItemInactive { |
| 53 | + width:36px; |
| 54 | + height:19px; |
| 55 | + background-image:url('wikicode-button.png'); |
| 56 | +} |
| 57 | + |
| 58 | +.buttonsPanel .resetButtonItemInactive { |
| 59 | + width:36px; |
| 60 | + height:19px; |
| 61 | + background-image:url('reset-button.png'); |
| 62 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/SlippyMap/SlippyMap.css |
___________________________________________________________________ |
Name: svn:eol-style |
1 | 63 | + native |
Index: trunk/extensions/SlippyMap/SlippyMap.hooks.php |
— | — | @@ -0,0 +1,172 @@ |
| 2 | +<?php |
| 3 | +if ( ! defined( 'MEDIAWIKI' ) ) |
| 4 | + die(); |
| 5 | + |
| 6 | +class SlippyMapHooks { |
| 7 | + |
| 8 | + var $mapId; |
| 9 | + |
| 10 | + /** |
| 11 | + * Property: SlippyMapMarkerList |
| 12 | + * Evil hack as documented at |
| 13 | + * http://www.mediawiki.org/wiki/Manual:Tag_extensions#How_can_I_avoid_modification_of_my_extension.27s_HTML_output.3F |
| 14 | + * This is here so that random <p> and <pre> tags aren't added to the inline JavaScript output |
| 15 | + */ |
| 16 | + var $SlippyMapMarkerList = array(); |
| 17 | + |
| 18 | + /** |
| 19 | + * Search string used to check for SlippyMap invocation |
| 20 | + */ |
| 21 | + protected static $WIKITEXT_PATTERN = "slippymap"; |
| 22 | + |
| 23 | + public function __construct() { |
| 24 | + $this->mapId = 0; |
| 25 | + } |
| 26 | + |
| 27 | + /** |
| 28 | + * Sets up the slippy map and links JavaScript files |
| 29 | + * |
| 30 | + * Register the extension with the WikiText parser |
| 31 | + * the first parameter is the name of the new tag. |
| 32 | + * In this case it defines the tag <slippymap> ... </slippymap> |
| 33 | + * the second parameter is the callback function for |
| 34 | + * processing the text between the tags |
| 35 | + * |
| 36 | + * @return true |
| 37 | + */ |
| 38 | + |
| 39 | + public function onParserFirstCallInit( ) { |
| 40 | + global $wgArticle, $wgOut, $wgParser, $wgScriptPath, $wgJsMimeType, $wgStyleVersion, $wgAutoLoadMaps; |
| 41 | + |
| 42 | + $smh = new SlippyMapHooks(); |
| 43 | + |
| 44 | + /** |
| 45 | + * If not a special page ( $wgArticle exists ), |
| 46 | + * then check for slippymap tag and |
| 47 | + * add openlayers if page includes slippymap |
| 48 | + * otherwise, do not add slippymap and openlayers js |
| 49 | + * where unnecessary and will slow page load time. |
| 50 | + */ |
| 51 | + if ( isset( $wgArticle ) && strstr($wgArticle->getRawText(), SlippyMapHooks::$WIKITEXT_PATTERN ) ) { |
| 52 | + |
| 53 | + wfLoadExtensionMessages( 'SlippyMap' ); |
| 54 | + |
| 55 | + if ( $wgAutoLoadMaps ) { |
| 56 | + $autoload = 'true'; |
| 57 | + } else { |
| 58 | + $autoload = 'false'; |
| 59 | + } |
| 60 | + |
| 61 | + $script = array( |
| 62 | + "<script type=\"$wgJsMimeType\">/*<![CDATA[*/", |
| 63 | + "var wgSlippyMapCode = " . Xml::encodeJsVar( wfMsg( 'slippymap_code' ) ) . ";", |
| 64 | + "var wgSlippyMapButtonCode = " . Xml::encodeJsVar( wfMsg( 'slippymap_button_code' ) ) . ";", |
| 65 | + "var wgSlippyMapResetview = " . Xml::encodeJsVar( wfMsg( 'slippymap_resetview' ) ) . ";", |
| 66 | + "var autoInitMaps = {$autoload};", |
| 67 | + "/*]]>*/</script>", |
| 68 | + ); |
| 69 | + |
| 70 | + $wgOut->addScript( implode( "\n\t\t", $script ) . "\n" ); |
| 71 | + $wgOut->addScript( "<script type='$wgJsMimeType' src='" . $wgScriptPath . "/extensions/SlippyMap/openlayers/lib/OpenLayers.js?{$wgStyleVersion}'></script>" ); |
| 72 | + $wgOut->addScript( "<script type='$wgJsMimeType' src='" . $wgScriptPath . "/extensions/SlippyMap/SlippyMap.js?{$wgStyleVersion}'></script>" ); |
| 73 | + $wgOut->addLink( array( 'rel' => 'stylesheet','type' => 'text/css','href' => $wgScriptPath . '/extensions/SlippyMap/SlippyMap.css' ) ); |
| 74 | + |
| 75 | + $wgParser->setHook( 'slippymap', array( $smh, 'wfParseMapAttributes' ) ); |
| 76 | + } |
| 77 | + |
| 78 | + return true; |
| 79 | + } |
| 80 | + |
| 81 | + public function wfParseMapAttributes( $input, $argv, $parser ) |
| 82 | + { |
| 83 | + global $wgOut, $SlippyMapMarkerList, $wgMapModes; |
| 84 | + |
| 85 | + /** |
| 86 | + * Support old style parameters from $input |
| 87 | + * Parse the pipe separated name value pairs (e.g. 'aaa=bbb|ccc=ddd') |
| 88 | + * With the new syntax we expect nothing in the $input, so this will result in '' values |
| 89 | + */ |
| 90 | + |
| 91 | + $oldStyleParamStrings = explode( '|', $input ); |
| 92 | + foreach ( $oldStyleParamStrings as $oldStyleParamString ) { |
| 93 | + $oldStyleParamString = trim( $oldStyleParamString ); |
| 94 | + $eqPos = strpos( $oldStyleParamString, "=" ); |
| 95 | + if ( $eqPos === false ) { |
| 96 | + $oldStyleParams[$oldStyleParamString] = 'true'; |
| 97 | + } else { |
| 98 | + $oldStyleParams[substr( $oldStyleParamString, 0, $eqPos )] = trim( htmlspecialchars( substr( $oldStyleParamString, $eqPos + 1 ) ) ); |
| 99 | + } |
| 100 | + } |
| 101 | + |
| 102 | + foreach ( $argv as $key=>$val ) { |
| 103 | + // Receive new style args: <slippymap aaa=bbb ccc=ddd></slippymap> |
| 104 | + if ( isset( $val ) ) { |
| 105 | + $key = strtolower( $key ); |
| 106 | + $mapParams[$key] = $val; |
| 107 | + } |
| 108 | + } |
| 109 | + |
| 110 | + /** |
| 111 | + * If using old style params, turn them into a mapParams array |
| 112 | + */ |
| 113 | + if ( ( count( $mapParams ) == 0 ) && ( count( $oldStyleParams ) > 0 ) ) { |
| 114 | + foreach ( $oldStyleParams as $key => $val ) { |
| 115 | + // Receive new style args: <slippymap aaa=bbb ccc=ddd></slippymap> |
| 116 | + if ( isset( $val ) ) { |
| 117 | + $key = strtolower( $key ); |
| 118 | + $mapParams[$key] =& $val; |
| 119 | + } |
| 120 | + } |
| 121 | + } |
| 122 | + |
| 123 | + /** |
| 124 | + * Give the map a unique id, so there can be multiple maps |
| 125 | + */ |
| 126 | + $mapParams['mapId'] = $this->mapId; |
| 127 | + |
| 128 | + if ( ! in_array( $mapParams['mode'], $wgMapModes ) ) { |
| 129 | + $errors = wfMsg( 'slippymap_invalidmode', htmlspecialchars( $this->mode ) ); |
| 130 | + $wgOut->addHTML( '<h3>' . $mapParams['mode'] . ' is an invalid map mode</h3>' ); |
| 131 | + } else { |
| 132 | + $output = ''; |
| 133 | + switch ( $mapParams['mode'] ) { |
| 134 | + case 'satellite': |
| 135 | + $map = new WorldWind( $mapParams ); |
| 136 | + break; |
| 137 | + default: |
| 138 | + $map = new SlippyMap( $mapParams ); |
| 139 | + } |
| 140 | + |
| 141 | + $output .= $map->getMap( ); |
| 142 | + $this->mapId++; |
| 143 | + $markercount = count( $SlippyMapMarkerList ); |
| 144 | + $pMarker = "SlippyMap-marker".$markercount."-SlippyMap"; |
| 145 | + $SlippyMapMarkerList[$markercount] = $output; |
| 146 | + return $pMarker; |
| 147 | + |
| 148 | + } |
| 149 | + |
| 150 | + } |
| 151 | + |
| 152 | + /** |
| 153 | + * Evil hack |
| 154 | + * @see http://www.mediawiki.org/wiki/Manual:Tag_extensions#How_can_I_avoid_modification_of_my_extension.27s_HTML_output.3F |
| 155 | + */ |
| 156 | + function wfSlippyMapParserAfterTidy( &$parser, &$text ) { |
| 157 | + global $SlippyMapMarkerList; |
| 158 | + $keys = array(); |
| 159 | + $marker_count = count( $SlippyMapMarkerList ); |
| 160 | + |
| 161 | + for ($i = 0; $i < $marker_count; $i++) { |
| 162 | + $keys[] = 'SlippyMap-marker' . $i . '-SlippyMap'; |
| 163 | + } |
| 164 | + |
| 165 | + $text = str_replace( $keys, $SlippyMapMarkerList, $text ); |
| 166 | + return true; |
| 167 | + } |
| 168 | + |
| 169 | + function error( $msg ) { |
| 170 | + $error = '<strong class="error">' . $msg . '</strong>'; |
| 171 | + return $error; |
| 172 | + } |
| 173 | +} |
Property changes on: trunk/extensions/SlippyMap/SlippyMap.hooks.php |
___________________________________________________________________ |
Name: svn:eol-style |
1 | 174 | + native |
Name: svn:executable |
2 | 175 | + * |
Index: trunk/extensions/SlippyMap/SlippyMap.class.php |
— | — | @@ -1,375 +1,450 @@ |
2 | 2 | <?php |
3 | | -# OpenStreetMap SlippyMap - MediaWiki extension |
4 | | -# |
5 | | -# This defines what happens when <slippymap> tag is placed in the wikitext |
6 | | -# |
7 | | -# We show a map based on the lat/lon/zoom data passed in. This extension brings in |
8 | | -# the OpenLayers javascript, to show a slippy map. |
9 | | -# |
10 | | -# Usage example: |
11 | | -# <slippymap lat="51.485" lon="-0.15" z="11" w="300" h="200" layer="osmarender" marker="0" /> |
12 | | -# |
13 | | -# Tile images are not cached local to the wiki. |
14 | | -# To acheive this (remove the OSM dependency) you might set up a squid proxy, |
15 | | -# and modify the requests URLs here accordingly. |
16 | | -# |
17 | | -# This file should be placed in the mediawiki 'extensions' directory |
18 | | -# ...and then it needs to be 'included' within LocalSettings.php |
19 | | -# |
20 | | -# ################################################################################# |
21 | | -# |
22 | | -# Copyright 2008 Harry Wood, Jens Frank, Grant Slater, Raymond Spekking and others |
23 | | -# |
24 | | -# This program is free software; you can redistribute it and/or modify |
25 | | -# it under the terms of the GNU General Public License as published by |
26 | | -# the Free Software Foundation; either version 2 of the License, or |
27 | | -# (at your option) any later version. |
28 | | -# |
29 | | -# This program is distributed in the hope that it will be useful, |
30 | | -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
31 | | -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
32 | | -# GNU General Public License for more details. |
33 | | -# |
34 | | -# You should have received a copy of the GNU General Public License |
35 | | -# along with this program; if not, write to the Free Software |
36 | | -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
37 | | -# |
38 | | -# @addtogroup Extensions |
39 | | -# |
| 3 | +/** |
| 4 | +* |
| 5 | +* @file |
| 6 | +* |
| 7 | +* @description |
| 8 | +* OpenStreetMap SlippyMap - MediaWiki extension |
| 9 | +* |
| 10 | +* This defines what happens when <slippymap> tag is placed in the wikitext |
| 11 | +* |
| 12 | +* We show a map based on the lat/lon/zoom data passed in. This extension brings in |
| 13 | +* the OpenLayers javascript, to show a slippy map. |
| 14 | +* |
| 15 | +* Usage example: |
| 16 | +* <slippymap lat="51.485" lon="-0.15" z="11" w="300" h="200" layer="osmarender" marker="0" /> |
| 17 | +* |
| 18 | +* Tile images are not cached local to the wiki. |
| 19 | +* To acheive this (remove the OSM dependency) you might set up a squid proxy, |
| 20 | +* and modify the requests URLs here accordingly. |
| 21 | +* |
| 22 | +* This file should be placed in the mediawiki 'extensions' directory |
| 23 | +* ...and then it needs to be 'included' within LocalSettings.php |
| 24 | +* |
| 25 | +* @license |
| 26 | +* |
| 27 | +* Copyright 2008 Harry Wood, Jens Frank, Grant Slater, Raymond Spekking and others |
| 28 | +* |
| 29 | +* This program is free software; you can redistribute it and/or modify |
| 30 | +* it under the terms of the GNU General Public License as published by |
| 31 | +* the Free Software Foundation; either version 2 of the License, or |
| 32 | +* (at your option) any later version. |
| 33 | +* |
| 34 | +* This program is distributed in the hope that it will be useful, |
| 35 | +* but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 36 | +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 37 | +* GNU General Public License for more details. |
| 38 | +* |
| 39 | +* You should have received a copy of the GNU General Public License |
| 40 | +* along with this program; if not, write to the Free Software |
| 41 | +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 42 | +* |
| 43 | +*/ |
40 | 44 | |
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 | +class SlippyMap { |
45 | 46 | |
46 | | -# The number of Slippy Maps we have had thus far, to get unique JavaScript variables |
47 | | -$SlippyMapCounter = 1; |
48 | | - |
49 | | -class SlippyMap { |
50 | | - # The callback function for converting the input text to HTML output |
51 | | - static function parse( $input, $argv ) { |
52 | | - global $SlippyMapMarkerList, $SlippyMapCounter; |
| 47 | + var $mapId; |
| 48 | + var $lat; |
| 49 | + var $lon; |
| 50 | + var $width; |
| 51 | + var $height; |
| 52 | + var $mode; |
| 53 | + var $layer; |
| 54 | + var $zoom; |
| 55 | + var $caption; |
| 56 | + var $scale; |
| 57 | + var $resolution; |
| 58 | + var $resolutions; |
| 59 | + var $scales; |
| 60 | + |
| 61 | + /** |
| 62 | + * minimum_longitude, minimum_latitude, maximum_longitude, maximum_latitude |
| 63 | + */ |
| 64 | + var $bounds; |
| 65 | + |
| 66 | + /* |
| 67 | + * Constants |
| 68 | + * Using static members instead of constants because arrays can't be const |
| 69 | + */ |
| 70 | + protected static $DEFAULT_IMAGE_FORMAT = "png"; |
| 71 | + |
| 72 | + /** |
| 73 | + * Supported map modes and their layer types |
| 74 | + */ |
| 75 | + public static $MAP_MODES = array( |
| 76 | + "mapnik", "osmarender", "maplint", "cycle" |
| 77 | + ); |
| 78 | + |
| 79 | + protected static $MAP_OPTIONS = array ( |
| 80 | +// 'staticRenderService' => 'http://tile.openstreetmap.org/cgi-bin/export?bbox=##bbox##&scale=##scale##&format=##format##', |
| 81 | + 'staticRenderService' => null, |
| 82 | + 'defaultZoomLevel' => 14, |
| 83 | + |
| 84 | + /* from OpenLayers XYZ.js */ |
| 85 | + 'defaultLayer' => 'mapnik', |
| 86 | + 'numZoomLevels' => 19, |
| 87 | + 'maxResolution' => 156543.0339, |
| 88 | + 'unit' => 'm', |
| 89 | + 'sphericalMercator' => true |
| 90 | + ); |
| 91 | + |
| 92 | + /** borrowed from OpenLayers.DOTS_PER_UNIT */ |
| 93 | + protected static $INCHES_PER_UNIT = array ( |
| 94 | + 'dd' => 4374754, |
| 95 | + 'm' => 39.3701 |
| 96 | + ); |
| 97 | + |
| 98 | + /** borrowed from OpenLayers.DOTS_PER_INCH */ |
| 99 | + protected static $DOTS_PER_INCH = 72; |
| 100 | + |
| 101 | + /** pixel size in meters */ |
| 102 | + protected static $PIXEL_SIZE = 0.00028; |
| 103 | + |
| 104 | + public function __construct( $mapParams ) { |
| 105 | + global $wgOut, $wgUser, $wgThumbLimits; |
53 | 106 | wfLoadExtensionMessages( 'SlippyMap' ); |
54 | 107 | |
55 | | - // Support old style parameters from $input |
56 | | - // Parse the pipe separated name value pairs (e.g. 'aaa=bbb|ccc=ddd') |
57 | | - // With the new syntax we expect nothing in the $input, so this will result in '' values |
58 | | - $oldStyleParamStrings = explode( '|', $input ); |
59 | | - foreach ( $oldStyleParamStrings as $oldStyleParamString ) { |
60 | | - $oldStyleParamString = trim( $oldStyleParamString ); |
61 | | - $eqPos = strpos( $oldStyleParamString, "=" ); |
62 | | - if ( $eqPos === false ) { |
63 | | - $oldStyleParams[$oldStyleParamString] = "true"; |
64 | | - } else { |
65 | | - $oldStyleParams[substr( $oldStyleParamString, 0, $eqPos )] = trim( htmlspecialchars( substr( $oldStyleParamString, $eqPos + 1 ) ) ); |
66 | | - } |
67 | | - } |
| 108 | + $this->errors = $this->validate(); |
| 109 | + if ( ! $this->errors ) |
| 110 | + return false; |
| 111 | + |
| 112 | + self::initMap( $mapParams ); |
| 113 | + self::setSize(); |
| 114 | + self::setZoom(); |
| 115 | + self::initResolutionsAndScales(); |
| 116 | + self::setBounds(); |
| 117 | + } |
68 | 118 | |
69 | | - // Receive new style args: <slippymap aaa=bbb ccc=ddd></slippymap> |
70 | | - if ( isset( $argv['lat'] ) ) { |
71 | | - $lat = $argv['lat']; |
72 | | - } else if ( isset( $oldStyleParams['lat'] ) ) { |
73 | | - $lat = $oldStyleParams['lat']; |
74 | | - } else { |
75 | | - $lat = ''; |
76 | | - } |
77 | | - if ( isset( $argv['lon'] ) ) { |
78 | | - $lon = $argv['lon']; |
79 | | - } else if ( isset( $oldStyleParams['lon'] ) ) { |
80 | | - $lon = $oldStyleParams['lon']; |
81 | | - } else { |
82 | | - $lon = ''; |
83 | | - } |
84 | | - if ( isset( $argv['z'] ) ) { |
85 | | - $zoom = $argv['z']; |
86 | | - } else if ( isset( $oldStyleParams['z'] ) ) { |
87 | | - $zoom = $oldStyleParams['z']; |
88 | | - } else { |
89 | | - $zoom = ''; |
90 | | - } |
91 | | - if ( isset( $argv['w'] ) ) { |
92 | | - $width = $argv['w']; |
93 | | - } else if ( isset( $oldStyleParams['w'] ) ) { |
94 | | - $width = $oldStyleParams['w']; |
95 | | - } else { |
96 | | - $width = ''; |
97 | | - } |
98 | | - if ( isset( $argv['h'] ) ) { |
99 | | - $height = $argv['h']; |
100 | | - } else if ( isset( $oldStyleParams['h'] ) ) { |
101 | | - $height = $oldStyleParams['h']; |
102 | | - } else { |
103 | | - $height = ''; |
104 | | - } |
105 | | - if ( isset( $argv['layer'] ) ) { |
106 | | - $layer = $argv['layer']; |
107 | | - } else if ( isset( $oldStyleParams['layer'] ) ) { |
108 | | - $layer = $oldStyleParams['layer']; |
109 | | - } else { |
110 | | - $layer = ''; |
111 | | - } |
112 | | - if ( isset( $argv['marker'] ) ) { |
113 | | - $marker = $argv['marker']; |
114 | | - } else { |
115 | | - $marker = ''; |
116 | | - } |
| 119 | + public function initMap( $mapParams ) { |
| 120 | + $this->mapId = $mapParams['mapId']; |
| 121 | + $this->lat = $mapParams['lat']; |
| 122 | + $this->lon = $mapParams['lon']; |
| 123 | + $this->width = $mapParams['w']; |
| 124 | + $this->height = $mapParams['h']; |
| 125 | + $this->mode = $mapParams['mode']; |
| 126 | + $this->zoom = $mapParams['zoom']; |
| 127 | + $this->caption = $mapParams['caption']; |
| 128 | + $this->layer = isset( $mapParams['layer'] ) ? strtolower($mapParams['layer']) : SlippyMap::$MAP_OPTIONS['defaultLayer']; |
| 129 | + $this->marker = ($mapParams['marker'] != '' && $mapParams['marker'] != '0' ? 1 : 0); |
117 | 130 | |
118 | | - $error = ''; |
| 131 | + // see if the 'z' paramater is used rather than 'zoom' (and allow it) |
| 132 | + if ( $this->zoom == '' && isset( $mapParams['z'] ) ) { |
| 133 | + $this->zoom = $mapParams['z']; |
| 134 | + } |
| 135 | + } |
| 136 | + |
| 137 | + public function getMap() { |
| 138 | + global $wgOut, $wgJsMimeType; |
119 | 139 | |
120 | | - // default values (meaning these parameters can be missed out) |
121 | | - if ( $width == '' ) $width = '450'; |
122 | | - if ( $height == '' ) $height = '320'; |
123 | | - if ( $layer == '' ) $layer = 'mapnik'; |
| 140 | + $mapCode .= <<<EOT |
| 141 | + <script type="{$wgJsMimeType}">slippymaps.push(new slippymap_map({$this->mapId}, { |
| 142 | + mode: '{$this->mode}', |
| 143 | + layer: '{$this->layer}', |
| 144 | + lat: {$this->lat}, |
| 145 | + lon: {$this->lon}, |
| 146 | + zoom: {$this->zoom}, |
| 147 | + width: {$this->width}, |
| 148 | + height: {$this->height}, |
| 149 | + marker: {$this->marker} |
| 150 | + }));</script> |
| 151 | +EOT; |
124 | 152 | |
125 | | - if ( $zoom == '' && isset( $argv['zoom'] ) ) { |
126 | | - $zoom = $argv['zoom']; // see if they used 'zoom' rather than 'z' (and allow it) |
| 153 | + // TODO: NOSCRIPT support |
| 154 | + if ( isset( SlippyMap::$MAP_OPTIONS['staticRenderService'] ) ) { |
| 155 | + $mapCode .= self::getStaticMap(); |
| 156 | + } else { |
| 157 | + $mapCode .= self::getDynamicMap(); |
127 | 158 | } |
| 159 | + return $mapCode; |
| 160 | + } |
128 | 161 | |
129 | | - $marker = ( $marker != '' && $marker != '0' ); |
| 162 | + public function getDynamicMap() { |
| 163 | + $mapCode .= <<<EOT |
| 164 | + <div class="mapframe" style="width:{$this->width}px"> |
| 165 | + <div id="map{$this->mapId}" class="map" style="width:{$this->width}px; height:{$this->height}px;"> |
| 166 | + <script type="{$wgJsMimeType}">slippymaps[{$this->mapId}].init();</script> |
| 167 | + </div> |
| 168 | +EOT; |
| 169 | + if ( $this->caption ) { |
| 170 | + $mapcode .= <<<EOT |
| 171 | + <div class="mapcaption">{$this->caption}</div> |
| 172 | +EOT; |
| 173 | + } |
130 | 174 | |
131 | | - // trim off the 'px' on the end of pixel measurement numbers (ignore if present) |
132 | | - if ( substr( $width, -2 ) == 'px' ) |
133 | | - $width = (int) substr( $width, 0, -2 ); |
| 175 | + $mapCode .= <<<EOT |
| 176 | + </div> |
| 177 | +EOT; |
| 178 | + return $mapCode; |
| 179 | + } |
134 | 180 | |
135 | | - if ( substr( $height, - 2 ) == 'px' ) |
136 | | - $height = (int) substr( $height, 0, -2 ); |
| 181 | + public function getStaticMap() { |
| 182 | + $clickToActivate = wfMsg('slippymap_clicktoactivate'); |
| 183 | + $staticmap = <<<EOT |
| 184 | + <div class="mapframe" style="width:{$this->width}px;"> |
| 185 | + <div id="map{$this->mapId}" class="map" style="width:{$this->width}px; height:{$this->height}px;"> |
| 186 | + <!-- Static preview --> |
| 187 | + <img |
| 188 | + id="mapPreview{$this->mapId}" |
| 189 | + class="mapPreview" |
| 190 | + src="{$this->getImgSrc()}" |
| 191 | + onclick="slippymaps[{$this->mapId}].init();" |
| 192 | + width="{$this->width}" |
| 193 | + height="{$this->height}" |
| 194 | + alt="Slippy Map" |
| 195 | + title="{$clickToActivate}"/> |
| 196 | + </div> |
| 197 | +EOT; |
137 | 198 | |
138 | | - if ( trim( $input ) != '' && sizeof( $oldStyleParamStrings ) < 3 ) { |
139 | | - $error = 'slippymap tag contents. Were you trying to input KML? KML support ' . |
140 | | - 'is disabled pending discussions about wiki syntax'; |
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 | | -// } |
155 | | - } else { |
156 | | - $showkml = false; |
157 | | - } |
| 199 | + if ( $this->caption ) { |
| 200 | + $staticmap .= '<div class="mapcaption">{$this->caption}</div>'; |
| 201 | + $staticmap .= '</div>'; |
| 202 | + } |
158 | 203 | |
159 | | - // Check required parameters values are provided |
160 | | - if ( $lat == '' ) $error .= wfMsg( 'slippymap_latmissing' ) . ' '; |
161 | | - if ( $lon == '' ) $error .= wfMsg( 'slippymap_lonmissing' ) . ' '; |
162 | | - if ( $zoom == '' ) $error .= wfMsg( 'slippymap_zoommissing' ) . ' '; |
| 204 | + return $staticmap; |
| 205 | + } |
163 | 206 | |
164 | | - if ( $error == '' ) { |
165 | | - // no errors so far. Now check the values |
166 | | - if ( !is_numeric( $width ) ) { |
167 | | - $error = wfMsg( 'slippymap_widthnan', $width ); |
168 | | - } else if ( !is_numeric( $height ) ) { |
169 | | - $error = wfMsg( 'slippymap_heightnan', $height ); |
170 | | - } else if ( !is_numeric( $zoom ) ) { |
171 | | - $error = wfMsg( 'slippymap_zoomnan', $zoom ); |
172 | | - } else if ( !is_numeric( $lat ) ) { |
173 | | - $error = wfMsg( 'slippymap_latnan', $lat ); |
174 | | - } else if ( !is_numeric( $lon ) ) { |
175 | | - $error = wfMsg( 'slippymap_lonnan', $lon ); |
176 | | - } else if ( $width > 1000 ) { |
177 | | - $error = wfMsg( 'slippymap_widthbig' ); |
178 | | - } else if ( $width < 100 ) { |
179 | | - $error = wfMsg( 'slippymap_widthsmall' ); |
180 | | - } else if ( $height > 1000 ) { |
181 | | - $error = wfMsg( 'slippymap_heightbig' ); |
182 | | - } else if ( $height < 100 ) { |
183 | | - $error = wfMsg( 'slippymap_heightsmall' ); |
184 | | - } else if ( $lat > 90 ) { |
185 | | - $error = wfMsg( 'slippymap_latbig' ); |
186 | | - } else if ( $lat < -90 ) { |
187 | | - $error = wfMsg( 'slippymap_latsmall' ); |
188 | | - } else if ( $lon > 180 ) { |
189 | | - $error = wfMsg( 'slippymap_lonbig' ); |
190 | | - } else if ( $lon < -180 ) { |
191 | | - $error = wfMsg( 'slippymap_lonsmall' ); |
192 | | - } else if ( $zoom < 0 ) { |
193 | | - $error = wfMsg( 'slippymap_zoomsmall' ); |
194 | | - } else if ( $zoom == 18 ) { |
195 | | - $error = wfMsg( 'slippymap_zoom18' ); |
196 | | - } else if ( $zoom > 17 ) { |
197 | | - $error = wfMsg( 'slippymap_zoombig' ); |
198 | | - } |
199 | | - } |
| 207 | + public function setZoom( $zoom = null ) { |
| 208 | + global $wgOut; |
| 209 | + if ( $this->zoom == '' ) $this->zoom = SlippyMap::$MAP_OPTIONS['defaultZoomLevel']; |
| 210 | + } |
| 211 | + |
| 212 | + public function setSize( $w = null, $h = null ) { |
| 213 | + global $wgUser, $wgOut, $wgThumbLimits; |
| 214 | + // set thumbsize based on user preferences |
| 215 | + $thumbsize = $wgThumbLimits[$wgUser->getOption( 'thumbsize' )]; |
200 | 216 | |
201 | | - // Find the tile server URL to use. Note that we could allow the user to override that with |
202 | | - // *any* tile server URL for more flexibility, but that might be a security concern. |
| 217 | + // default values (meaning these parameters can be missed out) |
| 218 | + if ( $this->width == '' ) $this->width = $thumbsize; |
| 219 | + if ( $this->height == '' ) $this->height = round( $thumbsize * .72 ); |
203 | 220 | |
204 | | - $layer = strtolower( $layer ); |
205 | | - $layerObjectDef = ''; |
206 | | - if ( $layer == 'osmarender' ) { |
207 | | - $layerObjectDef = 'OpenLayers.Layer.OSM.Osmarender("Osmarender");'; |
208 | | - } elseif ( $layer == 'mapnik' ) { |
209 | | - $layerObjectDef = 'OpenLayers.Layer.OSM.Mapnik("Mapnik");'; |
210 | | - } elseif ( $layer == 'maplint' ) { |
211 | | - $layerObjectDef = 'OpenLayers.Layer.OSM.Maplint("Maplint");'; |
212 | | - } else { |
213 | | - $error = wfMsg( 'slippymap_invalidlayer', htmlspecialchars( $layer ) ); |
214 | | - } |
| 221 | + // trim off the 'px' on the end of pixel measurement numbers (ignore if present) |
| 222 | + if ( substr( $this->width, -2 ) == 'px' ) |
| 223 | + $this->width = (int) substr( $this->width, 0, -2 ); |
215 | 224 | |
216 | | - if ( $error != "" ) { |
217 | | - // Something was wrong. Spew the error message and input text. |
218 | | - $output = ''; |
219 | | - $output .= "<span class=\"error\">" . wfMsg( 'slippymap_maperror' ) . ' ' . $error . "</span><br />"; |
220 | | - $output .= htmlspecialchars( $input ); |
221 | | - return $output; |
222 | | - } else { |
223 | | - $output = self::makeSlippyMapHTMLandJS($lon, $lat, $zoom, $height, $width, $layerObjectDef, $marker, $SlippyMapCounter++); |
| 225 | + if ( substr( $this->height, - 2 ) == 'px' ) |
| 226 | + $this->height = (int) substr( $this->height, 0, -2 ); |
224 | 227 | |
225 | | - $markercount = count($SlippyMapMarkerList); |
226 | | - $pMarker = "SlippyMap-marker".$markercount."-SlippyMap"; |
227 | | - $SlippyMapMarkerList[$markercount] = $output; |
228 | | - return $pMarker; |
229 | | - } |
230 | 228 | } |
231 | 229 | |
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) |
| 230 | + public function setBounds() { |
239 | 231 | |
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${unique}); |
248 | | -markers${unique}.addMarker(new OpenLayers.Marker( lonLat${unique}, icon${unique} )); |
249 | | -EOT; |
250 | | - } |
| 232 | + /* Determine scale and map bounds for static render request */ |
| 233 | + $this->resolution = $this->resolutions[round( $this->zoom )]; |
| 234 | + $this->scale = self::getScaleFromResolution( $this->resolution ); |
251 | 235 | |
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' ) ); |
| 236 | + /* |
| 237 | + * Calculate width for Mapnik output using a standard pixel size of 0.00028m |
| 238 | + * @see http://trac.mapnik.org/wiki/ScaleAndPpi |
| 239 | + */ |
| 240 | + $w_deg = $this->width * SlippyMap::$PIXEL_SIZE * $this->scale; |
| 241 | + $h_deg = $this->height * SlippyMap::$PIXEL_SIZE * $this->scale; |
255 | 242 | |
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(),'; |
| 243 | + $center = array( $this->lon, $this->lat ); |
| 244 | + if ( SlippyMap::$MAP_OPTIONS['sphericalMercator'] ) { |
| 245 | + // Calculate bounds within a spherical mercator projection if that is what the scale is based on |
| 246 | + $mercatorCenter = SlippyMap::forwardMercator( $center ); |
| 247 | + $mbounds = array( |
| 248 | + $mercatorCenter[0] - $w_deg / 2, |
| 249 | + $mercatorCenter[1] - $h_deg / 2, |
| 250 | + $mercatorCenter[0] + $w_deg / 2, |
| 251 | + $mercatorCenter[1] + $h_deg / 2 |
| 252 | + ); |
| 253 | + $this->bounds = SlippyMap::inverseMercator( $mbounds ); |
| 254 | + } |
| 255 | + else { |
| 256 | + // Calculate bounds within WGS84 |
| 257 | + $this->bounds = array( $center[0] - $w_deg / 2, $center[1] - $h_deg / 2, $center[0] + $w_deg / 2, $center[1] + $h_deg / 2 ); |
| 258 | + } |
| 259 | + } |
| 260 | + |
| 261 | + public function getImgSrc() { |
| 262 | + if ( $this->isValidMode() && isset( SlippyMap::$MAP_OPTIONS['staticRenderService'] ) ) { |
| 263 | + return $this->parameterize( SlippyMap::$MAP_OPTIONS['staticRenderService'], |
| 264 | + array( 'bbox' => implode( ',', $this->bounds ), |
| 265 | + 'scale' => $this->scale, |
| 266 | + 'lat' => $this->lat, |
| 267 | + 'long' => $this->lon, |
| 268 | + 'z' => $this->zoom, |
| 269 | + 'w' => $this->width, |
| 270 | + 'h' => $this->height, |
| 271 | + 'format' => SlippyMap::$DEFAULT_IMAGE_FORMAT |
| 272 | + ) |
| 273 | + ); |
262 | 274 | } |
| 275 | + } |
| 276 | + |
| 277 | + /** |
| 278 | + * Substitutes parameters in a template using double hash sign delimiters, for example: |
| 279 | + * |
| 280 | + * <code> |
| 281 | + * <tag xml:lang="##lang##"/> |
| 282 | + * </code> |
| 283 | + * |
| 284 | + * A corresponding parameter "lang" may then be used to provide a replacement that is |
| 285 | + * transparently substituted. |
| 286 | + * |
| 287 | + * @param string $template The template text |
| 288 | + * @param array $params A map with parameter names as keys and their replacements as values |
| 289 | + * @return string Parameterized text |
| 290 | + */ |
| 291 | + protected static function parameterize( $template, $params ) { |
| 292 | + foreach ( $params as $key => $value ) { |
| 293 | + $template = str_replace( "##{$key}##", $value, $template ); |
| 294 | + } |
| 295 | + return $template; |
| 296 | + } |
| 297 | + |
| 298 | + /** |
| 299 | + * Borrowed from OpenLayers.Util.getScaleFromResolution |
| 300 | + */ |
| 301 | + protected function getScaleFromResolution( $resolution ) { |
| 302 | + return $resolution * SlippyMap::$INCHES_PER_UNIT[SlippyMap::$MAP_OPTIONS['unit']] * SlippyMap::$DOTS_PER_INCH; |
| 303 | + } |
| 304 | + |
| 305 | + /** |
| 306 | + * Determines resolutions and scales based on a maximum resolution and number of zoom levels |
| 307 | + * Borrowed from OpenLayers.Layer.initResolutions |
| 308 | + */ |
| 309 | + protected function initResolutionsAndScales() { |
| 310 | + $this->resolutions = array(); |
| 311 | + $base = 2; |
| 312 | + |
| 313 | + for ( $i = 0; $i < SlippyMap::$MAP_OPTIONS['numZoomLevels']; $i++ ) { |
| 314 | + $this->resolutions[$i] = SlippyMap::$MAP_OPTIONS['maxResolution'] / pow( $base, $i ); |
| 315 | + $this->scales[$i] = $this->getScaleFromResolution( $this->resolutions[$i] ); |
| 316 | + } |
| 317 | + } |
| 318 | + |
| 319 | + /** |
| 320 | + * Convert from WGS84 to spherical mercator |
| 321 | + */ |
| 322 | + protected static function forwardMercator($lonlat) { |
| 323 | + for ($i=0; $i<count($lonlat); $i+=2) { |
| 324 | + /* lon */ |
| 325 | + $lonlat[$i] = $lonlat[$i] * (2 * M_PI * 6378137 / 2.0) / 180.0; |
| 326 | + |
| 327 | + /* lat */ |
| 328 | + $lonlat[$i+1] = log(tan((90 + $lonlat[$i+1]) * M_PI / 360.0)) / (M_PI / 180.0); |
| 329 | + $lonlat[$i+1] = $lonlat[$i+1] * (2 * M_PI * 6378137 / 2.0) / 180.0; |
| 330 | + } |
| 331 | + return $lonlat; |
| 332 | + } |
| 333 | + |
| 334 | + /** |
| 335 | + * Convert from spherical mercator to WGS84 |
| 336 | + */ |
| 337 | + protected static function inverseMercator($lonlat) { |
| 338 | + for ($i=0; $i<count($lonlat); $i+=2) { |
| 339 | + /* lon */ |
| 340 | + $lonlat[$i] = $lonlat[$i] / ((2 * M_PI * 6378137 / 2.0) / 180.0); |
| 341 | + |
| 342 | + /* lat */ |
| 343 | + $lonlat[$i+1] = $lonlat[$i+1] / ((2 * M_PI * 6378137 / 2.0) / 180.0); |
| 344 | + $lonlat[$i+1] = 180.0 / M_PI * (2 * atan(exp($lonlat[$i+1] * M_PI / 180.0)) - M_PI / 2); |
| 345 | + } |
| 346 | + |
| 347 | + return $lonlat; |
| 348 | + } |
263 | 349 | |
264 | | - $output = <<<EOT |
265 | | -<!-- Slippy Map --> |
| 350 | + public function validMode( $mode ) { |
| 351 | + global $wgMapModes; |
| 352 | + $this->errors = ''; |
| 353 | + |
| 354 | + if ( ! in_array( $mode, $wgMapModes ) ) { |
| 355 | + $this->errors .= wfMsg( 'slippymap_invalidmode', htmlspecialchars( $this->mode ) ); |
| 356 | + return false; |
| 357 | + } |
266 | 358 | |
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> |
| 359 | + return true; |
| 360 | + } |
| 361 | + |
| 362 | + public function validate() { |
| 363 | + wfLoadExtensionMessages( 'SlippyMap' ); |
| 364 | + $errors = null; |
| 365 | + |
| 366 | + if ( $this->lat == '' ) $errors .= wfMsg( 'slippymap_latmissing' ) . ' '; |
| 367 | + if ( $this->lon == '' ) $errors .= wfMsg( 'slippymap_lonmissing' ) . ' '; |
| 368 | + if ( $this->zoom == '' ) $errors .= wfMsg( 'slippymap_zoommissing' ) . ' '; |
271 | 369 | |
272 | | -<!-- bring in the OpenLayers javascript library --> |
273 | | -<script src="http://openlayers.org/api/OpenLayers.js"></script> |
| 370 | + if ( $errors == '' ) { |
| 371 | + // no errors so far. Now check the values |
| 372 | + if ( !is_numeric( $this->width ) ) { |
| 373 | + $errors = wfMsg( 'slippymap_widthnan', $this->width ); |
| 374 | + } else if ( !is_numeric( $this->height ) ) { |
| 375 | + $errors = wfMsg( 'slippymap_heightnan', $this->height ); |
| 376 | + } else if ( !is_numeric( $this->zoom ) ) { |
| 377 | + $errors = wfMsg( 'slippymap_zoomnan', $this->zoom ); |
| 378 | + } else if ( !is_numeric( $this->lat ) ) { |
| 379 | + $errors = wfMsg( 'slippymap_latnan', $this->lat ); |
| 380 | + } else if ( !is_numeric( $this->lon ) ) { |
| 381 | + $errors = wfMsg( 'slippymap_lonnan', $this->lon ); |
| 382 | + } else if ( $this->width > 1000 ) { |
| 383 | + $errors = wfMsg( 'slippymap_widthbig' ); |
| 384 | + } else if ( $this->width < 100 ) { |
| 385 | + $errors = wfMsg( 'slippymap_widthsmall' ); |
| 386 | + } else if ( $this->height > 1000 ) { |
| 387 | + $errors = wfMsg( 'slippymap_heightbig' ); |
| 388 | + } else if ( $this->height < 100 ) { |
| 389 | + $errors = wfMsg( 'slippymap_heightsmall' ); |
| 390 | + } else if ( $this->lat > 90 ) { |
| 391 | + $errors = wfMsg( 'slippymap_latbig' ); |
| 392 | + } else if ( $this->lat < -90 ) { |
| 393 | + $errors = wfMsg( 'slippymap_latsmall' ); |
| 394 | + } else if ( $this->lon > 180 ) { |
| 395 | + $errors = wfMsg( 'slippymap_lonbig' ); |
| 396 | + } else if ( $this->lon < -180 ) { |
| 397 | + $errors = wfMsg( 'slippymap_lonsmall' ); |
| 398 | + } else if ( $this->zoom < 0 ) { |
| 399 | + $errors = wfMsg( 'slippymap_zoomsmall' ); |
| 400 | + } else if ( $this->zoom == 18 ) { |
| 401 | + $errors = wfMsg( 'slippymap_zoom18' ); |
| 402 | + } else if ( $this->zoom > 17 ) { |
| 403 | + $errors = wfMsg( 'slippymap_zoombig' ); |
| 404 | + } |
| 405 | + } |
| 406 | + |
| 407 | + return $errors; |
| 408 | + } |
| 409 | + |
| 410 | + public function getErrors() { |
| 411 | + if ( $this->errors != "" ) { |
| 412 | + // Something was wrong. Spew the error message and input text. |
| 413 | + $output = ''; |
| 414 | + $output .= "<span class=\"error\">" . wfMsg( 'slippymap_maperror' ) . ' ' . $this->errors . "</span><br />"; |
| 415 | + $output .= htmlspecialchars( $input ); |
| 416 | + return $output; |
| 417 | + } |
| 418 | + } |
274 | 419 | |
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> |
| 420 | + public function getMapId() { |
| 421 | + return $this->mapId; |
| 422 | + } |
279 | 423 | |
280 | | -<script type="text/javascript"> |
281 | | - var lon${unique} = ${lon}; |
282 | | - var lat${unique} = ${lat}; |
283 | | - var zoom${unique} = ${zoom}; |
| 424 | + public function getLat() { |
| 425 | + return $this->lat; |
| 426 | + } |
284 | 427 | |
285 | | - var lonLat${unique}; |
286 | | - var map${unique}; |
| 428 | + public function getLon() { |
| 429 | + return $this->lon; |
| 430 | + } |
287 | 431 | |
288 | | - addOnloadHook( slippymap_init ); |
289 | | - |
290 | | - function slippymap_resetPosition${unique}() { |
291 | | - map${unique}.setCenter(lonLat${unique}, zoom${unique}); |
| 432 | + public function getWidth() { |
| 433 | + return $this->width; |
292 | 434 | } |
293 | 435 | |
294 | | - function slippymap_getWikicode${unique}() { |
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 | | - ); |
| 436 | + public function getHeight() { |
| 437 | + return $this->height; |
302 | 438 | } |
303 | 439 | |
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 | | - }); |
317 | | - |
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() ); |
322 | | - |
323 | | - $slippymap_code_marker |
324 | | - |
325 | | - map${unique}.setCenter(lonLat${unique}, zoom${unique}); |
326 | | - |
327 | | - var getWikiCodeButton${unique} = new OpenLayers.Control.Button({ |
328 | | - title: "${slippymap_button_code}", |
329 | | - displayClass: "getWikiCodeButton", |
330 | | - trigger: slippymap_getWikicode${unique} |
331 | | - }); |
332 | | - |
333 | | - var resetButton${unique} = new OpenLayers.Control.Button({ |
334 | | - title: "${slippymap_resetview}", |
335 | | - displayClass: "resetButton", |
336 | | - trigger: slippymap_resetPosition${unique} |
337 | | - }); |
338 | | - |
339 | | - var panel${unique} = new OpenLayers.Control.Panel( { displayClass: "buttonsPanel" } ); |
340 | | - panel${unique}.addControls([getWikiCodeButton${unique}, resetButton${unique}]); |
341 | | - map${unique}.addControl(panel${unique}); |
| 440 | + public function getMode() { |
| 441 | + return $this->mode; |
342 | 442 | } |
343 | | -</script> |
344 | 443 | |
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; |
359 | | - |
360 | | - return $output; |
| 444 | + public function getZoom() { |
| 445 | + return $this->zoom; |
361 | 446 | } |
362 | 447 | |
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'; |
371 | | - } |
372 | | - |
373 | | - $text = str_replace($keys, $SlippyMapMarkerList, $text); |
374 | | - return true; |
| 448 | + public function getLayer() { |
| 449 | + return $this->layer; |
375 | 450 | } |
376 | 451 | } |
Index: trunk/extensions/SlippyMap/SlippyMap.js |
— | — | @@ -0,0 +1,213 @@ |
| 2 | +/* |
| 3 | + * @file |
| 4 | + * |
| 5 | + * @description |
| 6 | + * |
| 7 | + * OpenStreetMap SlippyMap - MediaWiki extension |
| 8 | + * |
| 9 | + * This defines what happens when <slippymap> tag is placed in the wikitext |
| 10 | + * |
| 11 | + * We show a map based on the lat/lon/zoom data passed in. This extension brings in |
| 12 | + * the OpenLayers javascript, to show a slippy map. |
| 13 | + * |
| 14 | + * Usage example: |
| 15 | + * <slippymap lat=51.485 lon=-0.15 z=11 w=300 h=200 layer=osmarender></slippymap> |
| 16 | + * |
| 17 | + * Tile images are not cached local to the wiki. |
| 18 | + * To acheive this (remove the OSM dependency) you might set up a squid proxy, |
| 19 | + * and modify the requests URLs here accordingly. |
| 20 | + * |
| 21 | + * This file should be placed in the mediawiki 'extensions' directory |
| 22 | + * ...and then it needs to be 'included' within LocalSettings.php |
| 23 | + * |
| 24 | + * @license |
| 25 | + * |
| 26 | + * Copyright 2008 Harry Wood, Jens Frank, Grant Slater, Raymond Spekking and others |
| 27 | + * |
| 28 | + * This program is free software; you can redistribute it and/or modify |
| 29 | + * it under the terms of the GNU General Public License as published by |
| 30 | + * the Free Software Foundation; either version 2 of the License, or |
| 31 | + * (at your option) any later version. |
| 32 | + * |
| 33 | + * This program is distributed in the hope that it will be useful, |
| 34 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 35 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 36 | + * GNU General Public License for more details. |
| 37 | + * |
| 38 | + * You should have received a copy of the GNU General Public License |
| 39 | + * along with this program; if not, write to the Free Software |
| 40 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 41 | + * |
| 42 | + */ |
| 43 | + |
| 44 | +var slippymaps = new Array(); |
| 45 | +var mapId = 0; |
| 46 | +var layer = null; |
| 47 | + |
| 48 | +if (autoInitMaps) { |
| 49 | + addOnloadHook(slippymap_init); |
| 50 | + addOnloadHook(prepPopupMap); |
| 51 | +} |
| 52 | + |
| 53 | +function slippymap_init() { |
| 54 | + for (i=0; i < slippymaps.length; i++) { |
| 55 | + slippymaps[i].init(); |
| 56 | + } |
| 57 | +} |
| 58 | + |
| 59 | +function slippymap_map(mapId, mapParams) { |
| 60 | + var self = this; |
| 61 | + this.mapId = mapId; |
| 62 | + |
| 63 | + for (key in mapParams) |
| 64 | + this[key] = mapParams[key]; |
| 65 | + |
| 66 | + var buttonsPanel = new OpenLayers.Control.Panel( { displayClass: "buttonsPanel" } ); |
| 67 | + buttonsPanel.addControls([ new OpenLayers.Control.Button({ |
| 68 | + title: wgSlippyMapButtonCode, |
| 69 | + displayClass: "getWikiCodeButton", |
| 70 | + trigger: function() { self.getWikicode(); } |
| 71 | + }), |
| 72 | + new OpenLayers.Control.Button({ |
| 73 | + title: wgSlippyMapResetview, |
| 74 | + displayClass: "resetButton", |
| 75 | + trigger: function() { self.resetPosition(); } |
| 76 | + }) |
| 77 | + ]); |
| 78 | + |
| 79 | + this.mapOptions = { controls: [ new OpenLayers.Control.Navigation(), |
| 80 | + new OpenLayers.Control.ArgParser(), |
| 81 | + new OpenLayers.Control.Attribution(), |
| 82 | + new OpenLayers.Control.LayerSwitcher(), |
| 83 | + buttonsPanel ] |
| 84 | + }; |
| 85 | + |
| 86 | + /* Add the zoom bar control, except if the map is only little */ |
| 87 | + if (this.height > 320) |
| 88 | + this.mapOptions.controls.push(new OpenLayers.Control.PanZoomBar()); |
| 89 | + else if (this.height > 140) |
| 90 | + this.mapOptions.controls.push(new OpenLayers.Control.PanZoom()); |
| 91 | +} |
| 92 | + |
| 93 | +slippymap_map.prototype.init = function() { |
| 94 | + /* Swap out against the preview image */ |
| 95 | + var previewImage = document.getElementById('mapPreview' + this.mapId); |
| 96 | + if (previewImage) |
| 97 | + previewImage.style.display = 'none'; |
| 98 | + |
| 99 | + switch(this.mode) { |
| 100 | + case "satellite": |
| 101 | + /* Nasa WorldWind */ |
| 102 | + this.map = this.ww_create(this.mapId, this.lon, this.lat, this.zoom, this.layer); |
| 103 | + break; |
| 104 | + case "wms": |
| 105 | + /* wms map */ |
| 106 | + this.map = this.wms_create(this.mapId, this.lon, this.lat, this.zoom, this.layer); |
| 107 | + break; |
| 108 | + default: |
| 109 | + /* OpenStreetMap */ |
| 110 | + this.map = this.osm_create(this.mapId, this.lon, this.lat, this.zoom); |
| 111 | + } |
| 112 | + |
| 113 | + if (this.marker) { |
| 114 | + var markers = new OpenLayers.Layer.Markers( "Markers" ); |
| 115 | + this.map.addLayer(markers); |
| 116 | + var size = new OpenLayers.Size(20,34); |
| 117 | + var offset = new OpenLayers.Pixel(-(size.w/2), -size.h); |
| 118 | + var icon = new OpenLayers.Icon('http://boston.openguides.org/markers/YELLOW.png', size, offset); |
| 119 | + markers.addMarker(new OpenLayers.Marker(new OpenLayers.LonLat(this.lon, this.lat).transform(new OpenLayers.Projection('EPSG:4326'), this.map.getProjectionObject()), icon)); |
| 120 | + } |
| 121 | +} |
| 122 | + |
| 123 | +slippymap_map.prototype.osm_create = function(mapId, lon, lat, zoom) { |
| 124 | + var map; |
| 125 | + var osmLayer; |
| 126 | + map = new OpenLayers.Map('map' + mapId, this.mapOptions /* all provided for by OSM.js */); |
| 127 | + |
| 128 | + if (this.layer == 'mapnik' ) { |
| 129 | + osmLayer = new OpenLayers.Layer.OSM(); |
| 130 | + } else if (this.layer == 'osmarender' ) { |
| 131 | + osmLayer = new OpenLayers.Layer.OSM("t@h", |
| 132 | + [ "http://a.tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png", |
| 133 | + "http://b.tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png", |
| 134 | + "http://c.tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png"]); |
| 135 | + } else if (this.layer == 'maplint' ) { |
| 136 | + osmLayer = new OpenLayers.Layer.OSM("maplint", |
| 137 | + [ "http://a.tah.openstreetmap.org/Tiles/maplint/${z}/${x}/${y}.png", |
| 138 | + "http://b.tah.openstreetmap.org/Tiles/maplint/${z}/${x}/${y}.png", |
| 139 | + "http://c.tah.openstreetmap.org/Tiles/maplint/${z}/${x}/${y}.png"]); |
| 140 | + } else if (this.layer == 'cycle' ) { |
| 141 | + osmLayer = new OpenLayers.Layer.OSM("cycle", |
| 142 | + [ "http://a.thunderflames.org/tiles/cycle/${z}/${x}/${y}.png", |
| 143 | + "http://b.thunderflames.org/tiles/cycle/${z}/${x}/${y}.png", |
| 144 | + "http://c.thunderflames.org/tiles/cycle/${z}/${x}/${y}.png"]); |
| 145 | + } |
| 146 | + |
| 147 | + map.addLayers([osmLayer]); |
| 148 | + map.setCenter(new OpenLayers.LonLat(lon, lat).transform(new OpenLayers.Projection('EPSG:4326'), map.getProjectionObject()), zoom); |
| 149 | + return map; |
| 150 | +} |
| 151 | + |
| 152 | +/* Nasa WorldWind |
| 153 | + * TODO make configurable |
| 154 | + */ |
| 155 | +slippymap_map.prototype.ww_create = function(mapId, lon, lat, zoom, layer) { |
| 156 | + var map; |
| 157 | + var wwLayer; |
| 158 | + this.mapOptions.maxResolution = 1.6; |
| 159 | + this.mapOptions.numZoomLevels = 21; |
| 160 | + |
| 161 | + map = new OpenLayers.Map('map' + mapId, this.mapOptions); |
| 162 | + |
| 163 | + if (this.layer == 'urban' ) { |
| 164 | + wwLayer = new OpenLayers.Layer.WorldWind( 'urban', |
| 165 | + "http://worldwind25.arc.nasa.gov/tile/tile.aspx?", .8, 9, |
| 166 | + {T:"104"}, { tileSize: new OpenLayers.Size(512,512) }); |
| 167 | + // TODO |
| 168 | + } else if (this.layer == 'landsat') { |
| 169 | + |
| 170 | + // TODO |
| 171 | + } else if (this.layer == 'bluemarble') { |
| 172 | + |
| 173 | + } |
| 174 | + |
| 175 | + map.addLayers([wwLayer]); |
| 176 | + map.setCenter(new OpenLayers.LonLat(lon, lat), zoom); |
| 177 | + return map; |
| 178 | +} |
| 179 | + |
| 180 | +/* WMS custom map |
| 181 | + * TODO make configurable |
| 182 | + */ |
| 183 | +slippymap_map.prototype.wms_create = function(mapId, lon, lat, zoom) { |
| 184 | + /* ? */ |
| 185 | + var map; |
| 186 | + this.mapOptions.maxResolution = 360/512/16; |
| 187 | + this.mapOptions.numZoomLevels = 15; |
| 188 | + map = new OpenLayers.Map('map' + mapId, this.mapOptions); |
| 189 | + wmsLayer = new OpenLayers.Layer.WMS( |
| 190 | + "Fire detects", "http://map.ngdc.noaa.gov/wmsconnector/com.esri.wms.Esrimap/firedetects", |
| 191 | + { |
| 192 | + layers: 'firedetects', |
| 193 | + format: 'image/png' |
| 194 | + }); |
| 195 | + map.addLayers([wmsLayer]); |
| 196 | + map.setCenter(new OpenLayers.LonLat( lon, lat ), zoom); |
| 197 | + return map; |
| 198 | +} |
| 199 | + |
| 200 | +slippymap_map.prototype.resetPosition = function() { |
| 201 | + this.map.setCenter(new OpenLayers.LonLat(this.lon, this.lat).transform(new OpenLayers.Projection('EPSG:4326'), this.map.getProjectionObject()), this.zoom); |
| 202 | +} |
| 203 | + |
| 204 | +slippymap_map.prototype.getWikicode = function() { |
| 205 | + LL = this.map.getCenter().transform(this.map.getProjectionObject(), new OpenLayers.Projection("EPSG:4326")); |
| 206 | + Z = this.map.getZoom(); |
| 207 | + size = this.map.getSize(); |
| 208 | + |
| 209 | + prompt( |
| 210 | + wgSlippyMapCode, |
| 211 | + "<slippymap h=" + size.h + " w=" + size.w + " z=" + Z + " lat=" + LL.lat + " lon=" + LL.lon + " mode=" + this.mode + " layer=" + this.layer + " marker=" + this.marker + " />" |
| 212 | + ); |
| 213 | +} |
| 214 | + |
Property changes on: trunk/extensions/SlippyMap/SlippyMap.js |
___________________________________________________________________ |
Name: svn:eol-style |
1 | 215 | + native |
Name: svn:executable |
2 | 216 | + * |
Index: trunk/extensions/SlippyMap/SlippyMap.alias.php |
— | — | @@ -0,0 +1,16 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * Aliases for special pages |
| 5 | + * |
| 6 | + * @file |
| 7 | + * @ingroup Extensions |
| 8 | + */ |
| 9 | + |
| 10 | +$aliases = array(); |
| 11 | + |
| 12 | +/** English */ |
| 13 | +$aliases['en'] = array( |
| 14 | + 'SlippyMap' => array( 'SlippyMap' ) |
| 15 | +); |
| 16 | + |
| 17 | + |
Property changes on: trunk/extensions/SlippyMap/SlippyMap.alias.php |
___________________________________________________________________ |
Name: svn:eol-style |
1 | 18 | + native |
Name: svn:executable |
2 | 19 | + * |
Index: trunk/extensions/SlippyMap/SlippyMap.worldwind.php |
— | — | @@ -0,0 +1,142 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | +* |
| 5 | +* @file |
| 6 | +* |
| 7 | +* @description |
| 8 | +* OpenStreetMap SlippyMap - MediaWiki extension |
| 9 | +* |
| 10 | +* This defines what happens when <slippymap> tag is placed in the wikitext |
| 11 | +* |
| 12 | +* We show a map based on the lat/lon/zoom data passed in. This extension brings in |
| 13 | +* the OpenLayers javascript, to show a slippy map. |
| 14 | +* |
| 15 | +* Usage example: |
| 16 | +* <slippymap lat="51.485" lon="-0.15" z="11" w="300" h="200" layer="osmarender" marker="0" /> |
| 17 | +* |
| 18 | +* Tile images are not cached local to the wiki. |
| 19 | +* To acheive this (remove the OSM dependency) you might set up a squid proxy, |
| 20 | +* and modify the requests URLs here accordingly. |
| 21 | +* |
| 22 | +* This file should be placed in the mediawiki 'extensions' directory |
| 23 | +* ...and then it needs to be 'included' within LocalSettings.php |
| 24 | +* |
| 25 | +* @license |
| 26 | +* |
| 27 | +* Copyright 2008 Harry Wood, Jens Frank, Grant Slater, Raymond Spekking and others |
| 28 | +* |
| 29 | +* This program is free software; you can redistribute it and/or modify |
| 30 | +* it under the terms of the GNU General Public License as published by |
| 31 | +* the Free Software Foundation; either version 2 of the License, or |
| 32 | +* (at your option) any later version. |
| 33 | +* |
| 34 | +* This program is distributed in the hope that it will be useful, |
| 35 | +* but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 36 | +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 37 | +* GNU General Public License for more details. |
| 38 | +* |
| 39 | +* You should have received a copy of the GNU General Public License |
| 40 | +* along with this program; if not, write to the Free Software |
| 41 | +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 42 | +* |
| 43 | +*/ |
| 44 | + |
| 45 | +class WorldWind extends SlippyMap { |
| 46 | + |
| 47 | + /** |
| 48 | + * Supported map modes and their layer types |
| 49 | + */ |
| 50 | + public static $MAP_MODES = array( |
| 51 | + "urban", "landsat", "bluemarble" |
| 52 | + ); |
| 53 | + |
| 54 | + protected static $MAP_OPTIONS = array ( |
| 55 | + 'staticRenderService' => null, |
| 56 | + 'defaultZoomLevel' => 14, |
| 57 | + |
| 58 | + /* from OpenLayers XYZ.js */ |
| 59 | + 'defaultLayer' => 'landsat', |
| 60 | + 'numZoomLevels' => 19, |
| 61 | + 'maxResolution' => 156543.0339, |
| 62 | + 'unit' => 'm', |
| 63 | + 'sphericalMercator' => true |
| 64 | + ); |
| 65 | + |
| 66 | + public function __construct( $mapParams ) { |
| 67 | + global $wgOut, $wgUser, $wgThumbLimits; |
| 68 | + wfLoadExtensionMessages( 'SlippyMap' ); |
| 69 | + |
| 70 | + $this->errors = $this->validate(); |
| 71 | + if ( ! $this->errors ) |
| 72 | + return false; |
| 73 | + |
| 74 | + self::initMap( $mapParams ); |
| 75 | + self::setSize(); |
| 76 | + self::setZoom(); |
| 77 | + self::initResolutionsAndScales(); |
| 78 | + self::setBounds(); |
| 79 | + } |
| 80 | + |
| 81 | + public function initMap( $mapParams ) { |
| 82 | + $this->mapId = $mapParams['mapId']; |
| 83 | + $this->lat = $mapParams['lat']; |
| 84 | + $this->lon = $mapParams['lon']; |
| 85 | + $this->width = $mapParams['w']; |
| 86 | + $this->height = $mapParams['h']; |
| 87 | + $this->mode = $mapParams['mode']; |
| 88 | + $this->zoom = $mapParams['zoom']; |
| 89 | + $this->caption = $mapParams['caption']; |
| 90 | + $this->layer = isset( $mapParams['layer'] ) ? strtolower($mapParams['layer']) : WorldWind::$MAP_OPTIONS['defaultLayer']; |
| 91 | + $this->marker = ($mapParams['marker'] != '' && $mapParams['marker'] != '0' ? 1 : 0); |
| 92 | + |
| 93 | + // see if the 'z' paramater is used rather than 'zoom' (and allow it) |
| 94 | + if ( $this->zoom == '' && isset( $mapParams['z'] ) ) { |
| 95 | + $this->zoom = $mapParams['z']; |
| 96 | + } |
| 97 | + } |
| 98 | + |
| 99 | + public function getMap() { |
| 100 | + global $wgOut, $wgJsMimeType; |
| 101 | + |
| 102 | + $mapCode .= <<<EOT |
| 103 | + <script type="{$wgJsMimeType}">slippymaps.push(new slippymap_map({$this->mapId}, { |
| 104 | + mode: '{$this->mode}', |
| 105 | + layer: '{$this->layer}', |
| 106 | + lat: {$this->lat}, |
| 107 | + lon: {$this->lon}, |
| 108 | + zoom: {$this->zoom}, |
| 109 | + width: {$this->width}, |
| 110 | + height: {$this->height}, |
| 111 | + marker: {$this->marker} |
| 112 | + }));</script> |
| 113 | +EOT; |
| 114 | + |
| 115 | + $mapCode .= self::getDynamicMap(); |
| 116 | + |
| 117 | + return $mapCode; |
| 118 | + } |
| 119 | + |
| 120 | + public function getDynamicMap() { |
| 121 | + $mapCode .= <<<EOT |
| 122 | + <div class="mapframe" style="width:{$this->width}px"> |
| 123 | + <div id="map{$this->mapId}" class="map" style="width:{$this->width}px; height:{$this->height}px;"> |
| 124 | + <script type="{$wgJsMimeType}">slippymaps[{$this->mapId}].init();</script> |
| 125 | + </div> |
| 126 | +EOT; |
| 127 | + if ( $this->caption ) { |
| 128 | + $mapcode .= <<<EOT |
| 129 | + <div class="mapcaption">{$this->caption}</div> |
| 130 | +EOT; |
| 131 | + } |
| 132 | + |
| 133 | + $mapCode .= <<<EOT |
| 134 | + </div> |
| 135 | +EOT; |
| 136 | + return $mapCode; |
| 137 | + } |
| 138 | + |
| 139 | + public function setZoom( $zoom = null ) { |
| 140 | + global $wgOut; |
| 141 | + if ( $this->zoom == '' ) $this->zoom = WorldWind::$MAP_OPTIONS['defaultZoomLevel']; |
| 142 | + } |
| 143 | +} |
Property changes on: trunk/extensions/SlippyMap/SlippyMap.worldwind.php |
___________________________________________________________________ |
Name: svn:eol-style |
1 | 144 | + native |
Name: svn:executable |
2 | 145 | + * |