r65433 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r65432‎ | r65433 | r65434 >
Date:19:21, 22 April 2010
Author:jeroendedauw
Status:deferred
Tags:
Comment:
Changes for 0.6 - moved a bunch of directories to get a more logic structure
Modified paths:
  • /trunk/extensions/Maps/Services (added) (history)
  • /trunk/extensions/Maps/Services/GoogleMaps (added) (history)
  • /trunk/extensions/Maps/Services/GoogleMaps/GoogleMapFunctions.js (added) (history)
  • /trunk/extensions/Maps/Services/GoogleMaps/GoogleMapFunctions.min.js (added) (history)
  • /trunk/extensions/Maps/Services/GoogleMaps/Maps_GoogleMaps.php (added) (history)
  • /trunk/extensions/Maps/Services/GoogleMaps/Maps_GoogleMapsDispMap.php (added) (history)
  • /trunk/extensions/Maps/Services/GoogleMaps/Maps_GoogleMapsDispPoint.php (added) (history)
  • /trunk/extensions/Maps/Services/GoogleMaps3 (added) (history)
  • /trunk/extensions/Maps/Services/GoogleMaps3/GoogleMap3Functions.js (added) (history)
  • /trunk/extensions/Maps/Services/GoogleMaps3/GoogleMap3Functions.min.js (added) (history)
  • /trunk/extensions/Maps/Services/GoogleMaps3/Maps_GoogleMaps3.php (added) (history)
  • /trunk/extensions/Maps/Services/GoogleMaps3/Maps_GoogleMaps3DispMap.php (added) (history)
  • /trunk/extensions/Maps/Services/GoogleMaps3/Maps_GoogleMaps3DispPoint.php (added) (history)
  • /trunk/extensions/Maps/Services/OpenLayers (added) (history)
  • /trunk/extensions/Maps/Services/OpenLayers/Maps_OpenLayers.php (added) (history)
  • /trunk/extensions/Maps/Services/OpenLayers/Maps_OpenLayersDispMap.php (added) (history)
  • /trunk/extensions/Maps/Services/OpenLayers/Maps_OpenLayersDispPoint.php (added) (history)
  • /trunk/extensions/Maps/Services/OpenLayers/OpenLayerFunctions.js (added) (history)
  • /trunk/extensions/Maps/Services/OpenLayers/OpenLayerFunctions.min.js (added) (history)
  • /trunk/extensions/Maps/Services/OpenStreetMap (added) (history)
  • /trunk/extensions/Maps/Services/OpenStreetMap/Maps_OSM.php (added) (history)
  • /trunk/extensions/Maps/Services/OpenStreetMap/Maps_OSMCgiBin.php (added) (history)
  • /trunk/extensions/Maps/Services/OpenStreetMap/Maps_OSMDispMap.php (added) (history)
  • /trunk/extensions/Maps/Services/OpenStreetMap/Maps_OSMDispPoint.php (added) (history)
  • /trunk/extensions/Maps/Services/OpenStreetMap/OSMFunctions.js (added) (history)
  • /trunk/extensions/Maps/Services/OpenStreetMap/OSMFunctions.min.js (added) (history)
  • /trunk/extensions/Maps/Services/YahooMaps (added) (history)
  • /trunk/extensions/Maps/Services/YahooMaps/Maps_YahooMaps.php (added) (history)
  • /trunk/extensions/Maps/Services/YahooMaps/Maps_YahooMapsDispMap.php (added) (history)
  • /trunk/extensions/Maps/Services/YahooMaps/Maps_YahooMapsDispPoint.php (added) (history)
  • /trunk/extensions/Maps/Services/YahooMaps/YahooMapFunctions.js (added) (history)
  • /trunk/extensions/Maps/Services/YahooMaps/YahooMapFunctions.min.js (added) (history)

Diff [purge]

Index: trunk/extensions/Maps/Services/GoogleMaps3/Maps_GoogleMaps3DispPoint.php
@@ -0,0 +1,89 @@
 2+<?php
 3+
 4+/**
 5+ * File holding the MapsGoogleMaps3DispPoint class.
 6+ *
 7+ * @file Maps_GoogleMaps3DispPoint.php
 8+ * @ingroup MapsGoogleMaps3
 9+ *
 10+ * @author Jeroen De Dauw
 11+ */
 12+
 13+if ( !defined( 'MEDIAWIKI' ) ) {
 14+ die( 'Not an entry point.' );
 15+}
 16+
 17+/**
 18+ * Class for handling the display_point(s) parser functions with Google Maps v3.
 19+ *
 20+ * @ingroup MapsGoogleMaps3
 21+ *
 22+ * @author Jeroen De Dauw
 23+ */
 24+final class MapsGoogleMaps3DispPoint extends MapsBasePointMap {
 25+
 26+ public $serviceName = MapsGoogleMaps3::SERVICE_NAME;
 27+
 28+ protected $markerStringFormat = 'getGMaps3MarkerData(lat, lon, \'title\', \'label\', "icon")';
 29+
 30+ protected function getDefaultZoom() {
 31+ global $egMapsGMaps3Zoom;
 32+ return $egMapsGMaps3Zoom;
 33+ }
 34+
 35+ /**
 36+ * @see MapsBaseMap::doMapServiceLoad()
 37+ *
 38+ */
 39+ protected function doMapServiceLoad() {
 40+ global $egGMaps3OnThisPage;
 41+
 42+ MapsGoogleMaps3::addGMap3Dependencies( $this->output );
 43+ $egGMaps3OnThisPage++;
 44+
 45+ $this->elementNr = $egGMaps3OnThisPage;
 46+ }
 47+
 48+ /**
 49+ * @see MapsBaseMap::addSpecificMapHTML()
 50+ *
 51+ */
 52+ public function addSpecificMapHTML( Parser $parser ) {
 53+ global $egMapsGMaps3Prefix, $egGMaps3OnThisPage;
 54+
 55+ $mapName = $egMapsGMaps3Prefix . '_' . $egGMaps3OnThisPage;
 56+
 57+ $this->output .= Html::element(
 58+ 'div',
 59+ array(
 60+ 'id' => $mapName,
 61+ 'width' => $this->width,
 62+ 'height' => $this->height
 63+ ),
 64+ null
 65+ );
 66+
 67+ $parser->getOutput()->addHeadItem(
 68+ Html::inlineScript( <<<EOT
 69+addOnloadHook(
 70+ function() {
 71+ initGMap3(
 72+ '$mapName',
 73+ {
 74+ zoom: $this->zoom,
 75+ lat: $this->centreLat,
 76+ lon: $this->centreLon,
 77+ types: [],
 78+ mapTypeId: $this->type
 79+ },
 80+ [$this->markerString]
 81+ );
 82+ }
 83+);
 84+EOT
 85+ )
 86+ );
 87+ }
 88+
 89+}
 90+
Index: trunk/extensions/Maps/Services/GoogleMaps3/GoogleMap3Functions.js
@@ -0,0 +1,41 @@
 2+ /**
 3+ * Javascript functions for Google Maps v3 functionallity in Maps.
 4+ *
 5+ * @file GoogleMap3Functions.js
 6+ * @ingroup MapsGoogleMaps3
 7+ *
 8+ * @author Jeroen De Dauw
 9+ */
 10+
 11+/**
 12+ * Created a new Map object with the provided properties and markers.
 13+ */
 14+function initGMap3(name, options, markerData) {
 15+ options.center = new google.maps.LatLng(options.lat, options.lon);
 16+
 17+ var map = new google.maps.Map(document.getElementById(name), options);
 18+
 19+ // TODO: types - http://code.google.com/apis/maps/documentation/v3/reference.html#MapTypeRegistry
 20+
 21+ for (marker in markerData) getGMaps3Marker(map, markerData[marker]);
 22+}
 23+
 24+function getGMaps3Marker(map, data) {
 25+ var marker = new google.maps.Marker({position: data.position, map: map, title: data.title, icon: data.icon});
 26+
 27+ var bothTxtAreSet = data.title.length > 0 && data.label.length > 0;
 28+ var popupText = bothTxtAreSet ? '<b>' + data.title + '</b><hr />' + data.label : data.title + data.label;
 29+
 30+ var infowindow = new google.maps.InfoWindow({content: popupText});
 31+
 32+ google.maps.event.addListener(marker, "click", function() {
 33+ infowindow.close();
 34+ infowindow.open(map, marker);
 35+ });
 36+
 37+ return marker;
 38+}
 39+
 40+function getGMaps3MarkerData(lat, lon, title, label, icon) {
 41+ return {position: new google.maps.LatLng(lat, lon), title: title, label: label, icon: icon};
 42+}
\ No newline at end of file
Index: trunk/extensions/Maps/Services/GoogleMaps3/GoogleMap3Functions.min.js
Index: trunk/extensions/Maps/Services/GoogleMaps3/Maps_GoogleMaps3DispMap.php
@@ -0,0 +1,87 @@
 2+<?php
 3+
 4+/**
 5+ * Class for handling the display_map parser function with Google Maps v3.
 6+ *
 7+ * @file Maps_GoogleMaps3DispMap.php
 8+ * @ingroup MapsGoogleMaps3
 9+ *
 10+ * @author Jeroen De Dauw
 11+ */
 12+
 13+if ( !defined( 'MEDIAWIKI' ) ) {
 14+ die( 'Not an entry point.' );
 15+}
 16+
 17+/**
 18+ * Class for handling the display_map parser functions with Google Maps v3.
 19+ *
 20+ * @ingroup MapsGoogleMaps3
 21+ *
 22+ * @author Jeroen De Dauw
 23+ */
 24+final class MapsGoogleMaps3DispMap extends MapsBaseMap {
 25+
 26+ public $serviceName = MapsGoogleMaps3::SERVICE_NAME;
 27+
 28+ protected function getDefaultZoom() {
 29+ global $egMapsGMaps3Zoom;
 30+ return $egMapsGMaps3Zoom;
 31+ }
 32+
 33+ /**
 34+ * @see MapsBaseMap::doMapServiceLoad()
 35+ *
 36+ */
 37+ protected function doMapServiceLoad() {
 38+ global $egGMaps3OnThisPage;
 39+
 40+ MapsGoogleMaps3::addGMap3Dependencies( $this->output );
 41+ $egGMaps3OnThisPage++;
 42+
 43+ $this->elementNr = $egGMaps3OnThisPage;
 44+ }
 45+
 46+ /**
 47+ * @see MapsBaseMap::addSpecificMapHTML()
 48+ *
 49+ */
 50+ public function addSpecificMapHTML( Parser $parser ) {
 51+ global $egMapsGMaps3Prefix, $egGMaps3OnThisPage;
 52+
 53+ $mapName = $egMapsGMaps3Prefix . '_' . $egGMaps3OnThisPage;
 54+
 55+ $this->output .= Html::element(
 56+ 'div',
 57+ array(
 58+ 'id' => $mapName,
 59+ 'width' => $this->width,
 60+ 'height' => $this->height
 61+ ),
 62+ null
 63+ );
 64+
 65+ $parser->getOutput()->addHeadItem(
 66+ Html::inlineScript( <<<EOT
 67+addOnloadHook(
 68+ function() {
 69+ initGMap3(
 70+ '$mapName',
 71+ {
 72+ zoom: $this->zoom,
 73+ lat: $this->centreLat,
 74+ lon: $this->centreLon,
 75+ types: [],
 76+ mapTypeId: $this->type
 77+ },
 78+ []
 79+ );
 80+ }
 81+);
 82+EOT
 83+ )
 84+ );
 85+ }
 86+
 87+}
 88+
Index: trunk/extensions/Maps/Services/GoogleMaps3/Maps_GoogleMaps3.php
@@ -0,0 +1,165 @@
 2+<?php
 3+
 4+/**
 5+ * This groupe contains all Google Maps v3 related files of the Maps extension.
 6+ *
 7+ * @defgroup MapsGoogleMaps3 Google Maps v3
 8+ * @ingroup Maps
 9+ */
 10+
 11+/**
 12+ * This file holds the general information for the Google Maps v3 service.
 13+ *
 14+ * @file Maps_GoogleMaps3.php
 15+ * @ingroup MapsGoogleMaps3
 16+ *
 17+ * @author Jeroen De Dauw
 18+ */
 19+
 20+if ( !defined( 'MEDIAWIKI' ) ) {
 21+ die( 'Not an entry point.' );
 22+}
 23+
 24+$wgAutoloadClasses['MapsGoogleMaps3'] = dirname( __FILE__ ) . '/Maps_GoogleMaps3.php';
 25+
 26+$wgHooks['MappingServiceLoad'][] = 'MapsGoogleMaps3::initialize';
 27+
 28+$wgAutoloadClasses['MapsGoogleMaps3DispMap'] = dirname( __FILE__ ) . '/Maps_GoogleMaps3DispMap.php';
 29+
 30+$egMapsServices[MapsGoogleMaps3::SERVICE_NAME] = array(
 31+ 'aliases' => array( 'google3', 'googlemap3', 'gmap3', 'gmaps3' ),
 32+ 'features' => array(
 33+ 'display_map' => 'MapsGoogleMaps3DispMap',
 34+ )
 35+);
 36+
 37+/**
 38+ * Class for Google Maps v3 initialization.
 39+ *
 40+ * @ingroup MapsGoogleMaps3
 41+ *
 42+ * @author Jeroen De Dauw
 43+ */
 44+class MapsGoogleMaps3 {
 45+
 46+ const SERVICE_NAME = 'googlemaps3';
 47+
 48+ public static function initialize() {
 49+ global $wgAutoloadClasses, $egMapsServices;
 50+
 51+ self::initializeParams();
 52+
 53+ Validator::addOutputFormat( 'gmap3type', array( 'MapsGoogleMaps3', 'setGMapType' ) );
 54+ Validator::addOutputFormat( 'gmap3types', array( 'MapsGoogleMaps3', 'setGMapTypes' ) );
 55+
 56+ return true;
 57+ }
 58+
 59+ private static function initializeParams() {
 60+ global $egMapsServices, $egMapsGMaps3Type, $egMapsGMaps3Types;
 61+
 62+ $allowedTypes = self::getTypeNames();
 63+
 64+ $egMapsServices[self::SERVICE_NAME]['parameters'] = array(
 65+ 'type' => array(
 66+ 'aliases' => array( 'map-type', 'map type' ),
 67+ 'criteria' => array(
 68+ 'in_array' => $allowedTypes
 69+ ),
 70+ 'default' => $egMapsGMaps3Type, // FIXME: default value should not be used when not present in types parameter.
 71+ 'output-type' => 'gmap3type'
 72+ ),
 73+ /*
 74+ 'types' => array(
 75+ 'type' => array('string', 'list'),
 76+ 'aliases' => array('map-types', 'map types'),
 77+ 'criteria' => array(
 78+ 'in_array' => $allowedTypes
 79+ ),
 80+ 'default' => $egMapsGMaps3Types,
 81+ 'output-types' => array('gmap3types', 'list')
 82+ ),
 83+ */
 84+ );
 85+ }
 86+
 87+ private static $mapTypes = array(
 88+ 'normal' => 'ROADMAP',
 89+ 'roadmap' => 'ROADMAP',
 90+ 'satellite' => 'SATELLITE',
 91+ 'hybrid' => 'HYBRID',
 92+ 'terrain' => 'TERRAIN',
 93+ 'physical' => 'TERRAIN'
 94+ );
 95+
 96+ /**
 97+ * Returns the names of all supported map types.
 98+ *
 99+ * @return array
 100+ */
 101+ public static function getTypeNames() {
 102+ return array_keys( self::$mapTypes );
 103+ }
 104+
 105+ /**
 106+ * Changes the map type name into the corresponding Google Maps API v3 identifier.
 107+ *
 108+ * @param string $type
 109+ *
 110+ * @return string
 111+ */
 112+ public static function setGMapType( &$type ) {
 113+ $type = 'google.maps.MapTypeId.' . self::$mapTypes[ $type ];
 114+ }
 115+
 116+ /**
 117+ * Changes the map type names into the corresponding Google Maps API v3 identifiers.
 118+ *
 119+ * @param array $types
 120+ *
 121+ * @return array
 122+ */
 123+ public static function setGMapTypes( array &$types ) {
 124+ for ( $i = count( $types ) - 1; $i >= 0; $i-- ) {
 125+ self::setGMapType( $types[$i] );
 126+ }
 127+ }
 128+
 129+ /**
 130+ * Add references to the Google Maps API v3 and required JS file to the provided output
 131+ *
 132+ * @param string $output
 133+ */
 134+ public static function addGMap3Dependencies( &$output ) {
 135+ global $wgJsMimeType, $wgLang;
 136+ global $egGMaps3OnThisPage, $egMapsStyleVersion, $egMapsJsExt, $egMapsScriptPath;
 137+
 138+ if ( empty( $egGMaps3OnThisPage ) ) {
 139+ $egGMaps3OnThisPage = 0;
 140+
 141+ $languageCode = self::getMappedLanguageCode( $wgLang->getCode() );
 142+ $output .= "<script type='$wgJsMimeType' src='http://maps.google.com/maps/api/js?sensor=false&amp;language={$languageCode}'></script><script type='$wgJsMimeType' src='$egMapsScriptPath/Services/GoogleMaps3/GoogleMap3Functions{$egMapsJsExt}?$egMapsStyleVersion'></script>";
 143+ }
 144+ }
 145+
 146+ /**
 147+ * Maps language codes to Google Maps API v3 compatible values.
 148+ *
 149+ * @param string $code
 150+ *
 151+ * @return string The mapped code
 152+ */
 153+ private static function getMappedLanguageCode( $code ) {
 154+ $mappings = array(
 155+ 'en_gb' => 'en-gb',// v3 supports en_gb - but wants us to call it en-gb
 156+ 'he' => 'iw', // iw is googlish for hebrew
 157+ 'fj' => 'fil', // google does not support Fijian - use Filipino as close(?) supported relative
 158+ );
 159+ if ( array_key_exists( $code, $mappings ) ) {
 160+ $code = $mappings[$code];
 161+ }
 162+ return $code;
 163+ }
 164+
 165+}
 166+
\ No newline at end of file
Index: trunk/extensions/Maps/Services/YahooMaps/Maps_YahooMapsDispPoint.php
@@ -0,0 +1,84 @@
 2+<?php
 3+
 4+/**
 5+ * File holding the MapsYahooMapsDispPoint class.
 6+ *
 7+ * @file Maps_YahooMapsDispPoint.php
 8+ * @ingroup MapsYahooMaps
 9+ *
 10+ * @author Jeroen De Dauw
 11+ */
 12+
 13+if ( !defined( 'MEDIAWIKI' ) ) {
 14+ die( 'Not an entry point.' );
 15+}
 16+
 17+/**
 18+ * Class for handling the display_point(s) parser functions with Yahoo! Maps.
 19+ *
 20+ * @author Jeroen De Dauw
 21+ */
 22+class MapsYahooMapsDispPoint extends MapsBasePointMap {
 23+
 24+ public $serviceName = MapsYahooMaps::SERVICE_NAME;
 25+
 26+ protected $markerStringFormat = 'getYMarkerData(lat, lon, \'title\', \'label\', "icon")';
 27+
 28+ protected function getDefaultZoom() {
 29+ global $egMapsYahooMapsZoom;
 30+ return $egMapsYahooMapsZoom;
 31+ }
 32+
 33+ /**
 34+ * @see MapsBaseMap::doMapServiceLoad()
 35+ *
 36+ */
 37+ protected function doMapServiceLoad() {
 38+ global $egYahooMapsOnThisPage;
 39+
 40+ MapsYahooMaps::addYMapDependencies( $this->output );
 41+ $egYahooMapsOnThisPage++;
 42+
 43+ $this->elementNr = $egYahooMapsOnThisPage;
 44+ }
 45+
 46+ /**
 47+ * @see MapsBaseMap::addSpecificMapHTML()
 48+ *
 49+ */
 50+ public function addSpecificMapHTML( Parser $parser ) {
 51+ global $egMapsYahooMapsPrefix, $egYahooMapsOnThisPage;
 52+
 53+ $mapName = $egMapsYahooMapsPrefix . '_' . $egYahooMapsOnThisPage;
 54+
 55+ $this->output .= Html::element(
 56+ 'div',
 57+ array(
 58+ 'id' => $mapName,
 59+ 'style' => "width: $this->width; height: $this->height; background-color: #cccccc;",
 60+ ),
 61+ wfMsg('maps-loading-map')
 62+ );
 63+
 64+ $parser->getOutput()->addHeadItem(
 65+ Html::inlineScript( <<<EOT
 66+addOnloadHook(
 67+ function() {
 68+ initializeYahooMap(
 69+ '$mapName',
 70+ $this->centreLat,
 71+ $this->centreLon,
 72+ $this->zoom,
 73+ $this->type,
 74+ [$this->types],
 75+ [$this->controls],
 76+ $this->autozoom,
 77+ [$this->markerString]
 78+ );
 79+ }
 80+);
 81+EOT
 82+ ) );
 83+ }
 84+
 85+}
Index: trunk/extensions/Maps/Services/YahooMaps/YahooMapFunctions.js
@@ -0,0 +1,113 @@
 2+ /**
 3+ * Javascript functions for Yahoo! Maps functionallity in Maps and it's extensions
 4+ *
 5+ * @file YahooMapFunctions.js
 6+ * @ingroup MapsYahooMaps
 7+ *
 8+ * @author Jeroen De Dauw
 9+ */
 10+
 11+
 12+/**
 13+ * Returns YMarker object on the provided location.
 14+ * It will show a popup baloon with title and label when clicked, if either of these is set.
 15+ */
 16+function createYMarker(geoPoint, title, label, icon){
 17+ var newMarker;
 18+
 19+ if (icon != '') {
 20+ newMarker = new YMarker(geoPoint, new YImage(icon));
 21+ } else {
 22+ newMarker = new YMarker(geoPoint);
 23+ }
 24+
 25+ if ((title + label).length > 0) {
 26+ var bothTxtAreSet = title.length > 0 && label.length > 0;
 27+ var markerMarkup = bothTxtAreSet ? '<b>' + title + '</b><hr />' + label : title + label;
 28+ YEvent.Capture(newMarker, EventsList.MouseClick,
 29+ function(){
 30+ newMarker.openSmartWindow(markerMarkup);
 31+ }
 32+ );
 33+ }
 34+
 35+ return newMarker;
 36+}
 37+
 38+/**
 39+ * Returns YMap object with the provided properties and markers.
 40+ */
 41+function initializeYahooMap(mapName, lat, lon, zoom, type, types, controls, scrollWheelZoom, markers) {
 42+ var centre = (lon != null && lat != null) ? new YGeoPoint(lat, lon) : null;
 43+ return createYahooMap(document.getElementById(mapName), centre, zoom, type, types, controls, scrollWheelZoom, markers);
 44+}
 45+
 46+/**
 47+ * Returns YMap object with the provided properties.
 48+ */
 49+function createYahooMap(mapElement, centre, zoom, type, types, controls, scrollWheelZoom, markers) {
 50+ var typesContainType = false;
 51+
 52+ for (var i = 0; i < types.length; i++) {
 53+ if (types[i] == type) typesContainType = true;
 54+ }
 55+
 56+ if (! typesContainType) types.push(type);
 57+
 58+ var map = new YMap(mapElement, type);
 59+
 60+ map.removeZoomScale();
 61+
 62+ for (i in controls){
 63+ if (controls[i].toLowerCase() == 'auto-zoom') {
 64+ if (mapElement.offsetHeight > 42) controls[i] = mapElement.offsetHeight > 100 ? 'zoom' : 'zoom-short';
 65+ }
 66+
 67+ switch (controls[i]) {
 68+ case 'scale' :
 69+ map.addZoomScale();
 70+ case 'type' :
 71+ map.addTypeControl(types);
 72+ break;
 73+ case 'pan' :
 74+ map.addPanControl();
 75+ break;
 76+ case 'zoom' :
 77+ map.addZoomLong();
 78+ break;
 79+ case 'zoom-short' :
 80+ map.addZoomShort();
 81+ break;
 82+ }
 83+ }
 84+
 85+ map.setMapType(type);
 86+
 87+ if (!scrollWheelZoom) map.disableKeyControls();
 88+
 89+ var map_locations = ((zoom == null || centre == null) && markers.length > 1) ? Array() : null;
 90+
 91+ for (i in markers) {
 92+ var marker = markers[i];
 93+ map.addOverlay(createYMarker(marker.point, marker.title, marker.label, marker.icon));
 94+ if (map_locations != null) map_locations.push(marker.point);
 95+ }
 96+
 97+ if (map_locations != null) {
 98+ var centerAndZoom = map.getBestZoomAndCenter(map_locations);
 99+ map.drawZoomAndCenter(centerAndZoom.YGeoPoint, centerAndZoom.zoomLevel);
 100+ }
 101+
 102+ if (zoom != null) map.setZoomLevel(zoom);
 103+
 104+ // FIXME: the code after this line REFUSES to be executed
 105+ // This is probably caused by the YGeoPoint
 106+ // Notice that the map object will therefore NOT BE RETURNED!
 107+ if (centre != null) map.drawZoomAndCenter(centre);
 108+
 109+ return map;
 110+}
 111+
 112+function getYMarkerData(lat, lon, title, label, icon) {
 113+ return {point: new YGeoPoint(lat, lon), title: title, label: label, icon: icon};
 114+ }
\ No newline at end of file
Index: trunk/extensions/Maps/Services/YahooMaps/YahooMapFunctions.min.js
@@ -0,0 +1,3 @@
 2+function createYMarker(a,d,e,c){var b;b=c!=""?new YMarker(a,new YImage(c)):new YMarker(a);if((d+e).length>0){var g=(a=d.length>0&&e.length>0)?"<b>"+d+"</b><hr />"+e:d+e;YEvent.Capture(b,EventsList.MouseClick,function(){b.openSmartWindow(g)})}return b}function initializeYahooMap(a,d,e,c,b,g,k,h,i,j){d=e!=null&&d!=null?new YGeoPoint(d,e):null;return createYahooMap(document.getElementById(a),d,c,b,g,k,h,i,j)}
 3+function createYahooMap(a,d,e,c,b,g,k,h,i){for(var j=false,f=0;f<b.length;f++)if(b[f]==c)j=true;j||b.push(c);a=new YMap(a,c);a.removeZoomScale();for(f in g){if(g[f].toLowerCase()=="auto-zoom")if(i>42)g[f]=i>100?"zoom":"zoom-short";switch(g[f]){case "scale":a.addZoomScale();case "type":a.addTypeControl(b);break;case "pan":a.addPanControl();break;case "zoom":a.addZoomLong();break;case "zoom-short":a.addZoomShort();break}}a.setMapType(c);k||a.disableKeyControls();c=(e==null||d==null)&&h.length>1?Array():
 4+null;for(f in h){b=h[f];a.addOverlay(createYMarker(b.point,b.title,b.label,b.icon));c!=null&&c.push(b.point)}if(c!=null){h=a.getBestZoomAndCenter(c);a.drawZoomAndCenter(h.YGeoPoint,h.zoomLevel)}e!=null&&a.setZoomLevel(e);d!=null&&a.drawZoomAndCenter(d);return a}function getYMarkerData(a,d,e,c,b){return{point:new YGeoPoint(a,d),title:e,label:c,icon:b}};
\ No newline at end of file
Index: trunk/extensions/Maps/Services/YahooMaps/Maps_YahooMapsDispMap.php
@@ -0,0 +1,75 @@
 2+<?php
 3+
 4+/**
 5+ * Class for handling the display_map parser function with Yahoo! Maps
 6+ *
 7+ * @file Maps_YahooMapsDispMap.php
 8+ * @ingroup MapsYahooMaps
 9+ *
 10+ * @author Jeroen De Dauw
 11+ */
 12+
 13+if ( !defined( 'MEDIAWIKI' ) ) {
 14+ die( 'Not an entry point.' );
 15+}
 16+
 17+class MapsYahooMapsDispMap extends MapsBaseMap {
 18+
 19+ public $serviceName = MapsYahooMaps::SERVICE_NAME;
 20+
 21+ protected function getDefaultZoom() {
 22+ global $egMapsYahooMapsZoom;
 23+ return $egMapsYahooMapsZoom;
 24+ }
 25+
 26+ /**
 27+ * @see MapsBaseMap::doMapServiceLoad()
 28+ */
 29+ public function doMapServiceLoad() {
 30+ global $egYahooMapsOnThisPage;
 31+
 32+ MapsYahooMaps::addYMapDependencies( $this->output );
 33+ $egYahooMapsOnThisPage++;
 34+
 35+ $this->elementNr = $egYahooMapsOnThisPage;
 36+ }
 37+
 38+ /**
 39+ * @see MapsBaseMap::addSpecificMapHTML()
 40+ */
 41+ public function addSpecificMapHTML( Parser $parser ) {
 42+ global $egMapsYahooMapsPrefix, $egYahooMapsOnThisPage;
 43+
 44+ $mapName = $egMapsYahooMapsPrefix . '_' . $egYahooMapsOnThisPage;
 45+
 46+ $this->output .= Html::element(
 47+ 'div',
 48+ array(
 49+ 'id' => $mapName,
 50+ 'style' => "width: $this->width; height: $this->height; background-color: #cccccc;",
 51+ ),
 52+ wfMsg('maps-loading-map')
 53+ );
 54+
 55+ $parser->getOutput()->addHeadItem(
 56+ Html::inlineScript( <<<EOT
 57+addOnloadHook(
 58+ function() {
 59+ initializeYahooMap(
 60+ '$mapName',
 61+ $this->centreLat,
 62+ $this->centreLon,
 63+ $this->zoom,
 64+ $this->type,
 65+ [$this->types],
 66+ [$this->controls],
 67+ $this->autozoom,
 68+ []
 69+ );
 70+ }
 71+);
 72+EOT
 73+ ) );
 74+ }
 75+
 76+}
Index: trunk/extensions/Maps/Services/YahooMaps/Maps_YahooMaps.php
@@ -0,0 +1,172 @@
 2+<?php
 3+
 4+/**
 5+ * This groupe contains all Yahoo! Maps related files of the Maps extension.
 6+ *
 7+ * @defgroup MapsYahooMaps Yahoo! Maps
 8+ * @ingroup Maps
 9+ */
 10+
 11+/**
 12+ * This file holds the general information for the Yahoo! Maps service
 13+ *
 14+ * @file Maps_YahooMaps.php
 15+ * @ingroup MapsYahooMaps
 16+ *
 17+ * @author Jeroen De Dauw
 18+ */
 19+
 20+if ( !defined( 'MEDIAWIKI' ) ) {
 21+ die( 'Not an entry point.' );
 22+}
 23+
 24+$wgAutoloadClasses['MapsYahooMaps'] = dirname( __FILE__ ) . '/Maps_YahooMaps.php';
 25+
 26+$wgHooks['MappingServiceLoad'][] = 'MapsYahooMaps::initialize';
 27+
 28+$wgAutoloadClasses['MapsYahooMapsDispMap'] = dirname( __FILE__ ) . '/Maps_YahooMapsDispMap.php';
 29+$wgAutoloadClasses['MapsYahooMapsDispPoint'] = dirname( __FILE__ ) . '/Maps_YahooMapsDispPoint.php';
 30+
 31+$egMapsServices[MapsYahooMaps::SERVICE_NAME] = array(
 32+ 'aliases' => array( 'yahoo', 'yahoomap', 'ymap', 'ymaps' ),
 33+ 'features' => array(
 34+ 'display_point' => 'MapsYahooMapsDispPoint',
 35+ 'display_map' => 'MapsYahooMapsDispMap',
 36+ )
 37+);
 38+
 39+/**
 40+ * Class for Yahoo! Maps initialization.
 41+ *
 42+ * @ingroup MapsYahooMaps
 43+ *
 44+ * @author Jeroen De Dauw
 45+ */
 46+class MapsYahooMaps {
 47+
 48+ const SERVICE_NAME = 'yahoomaps';
 49+
 50+ public static function initialize() {
 51+ global $wgAutoloadClasses, $egMapsServices;
 52+
 53+ self::initializeParams();
 54+
 55+ Validator::addOutputFormat( 'ymaptype', array( __CLASS__, 'setYMapType' ) );
 56+ Validator::addOutputFormat( 'ymaptypes', array( __CLASS__, 'setYMapTypes' ) );
 57+
 58+ return true;
 59+ }
 60+
 61+ private static function initializeParams() {
 62+ global $egMapsServices, $egMapsYahooAutozoom, $egMapsYahooMapsType, $egMapsYahooMapsTypes, $egMapsYahooMapsZoom, $egMapsYMapControls;
 63+
 64+ $allowedTypes = MapsYahooMaps::getTypeNames();
 65+
 66+ $egMapsServices[self::SERVICE_NAME]['parameters'] = array(
 67+ 'controls' => array(
 68+ 'type' => array( 'string', 'list' ),
 69+ 'criteria' => array(
 70+ 'in_array' => self::getControlNames()
 71+ ),
 72+ 'default' => $egMapsYMapControls,
 73+ 'output-type' => array( 'list', ',', '\'' )
 74+ ),
 75+ 'type' => array (
 76+ 'aliases' => array( 'map-type', 'map type' ),
 77+ 'criteria' => array(
 78+ 'in_array' => $allowedTypes
 79+ ),
 80+ 'default' => $egMapsYahooMapsType, // FIXME: default value should not be used when not present in types parameter.
 81+ 'output-type' => 'ymaptype'
 82+ ),
 83+ 'types' => array (
 84+ 'type' => array( 'string', 'list' ),
 85+ 'aliases' => array( 'map-types', 'map types' ),
 86+ 'criteria' => array(
 87+ 'in_array' => $allowedTypes
 88+ ),
 89+ 'default' => $egMapsYahooMapsTypes,
 90+ 'output-types' => array( 'ymaptypes', 'list' )
 91+ ),
 92+ 'autozoom' => array(
 93+ 'type' => 'boolean',
 94+ 'aliases' => array( 'auto zoom', 'mouse zoom', 'mousezoom' ),
 95+ 'default' => $egMapsYahooAutozoom,
 96+ 'output-type' => 'boolstr'
 97+ ),
 98+ );
 99+
 100+ $egMapsServices[self::SERVICE_NAME]['parameters']['zoom']['criteria']['in_range'] = array( 1, 13 );
 101+ }
 102+
 103+ // http://developer.yahoo.com/maps/ajax
 104+ private static $mapTypes = array(
 105+ 'normal' => 'YAHOO_MAP_REG',
 106+ 'satellite' => 'YAHOO_MAP_SAT',
 107+ 'hybrid' => 'YAHOO_MAP_HYB',
 108+ );
 109+
 110+ /**
 111+ * Returns the names of all supported map types.
 112+ *
 113+ * @return array
 114+ */
 115+ public static function getTypeNames() {
 116+ return array_keys( self::$mapTypes );
 117+ }
 118+
 119+ /**
 120+ * Returns the names of all supported controls.
 121+ * This data is a copy of the one used to actually translate the names
 122+ * into the controls, since this resides client side, in YahooMapFunctions.js.
 123+ *
 124+ * @return array
 125+ */
 126+ public static function getControlNames() {
 127+ return array( 'scale', 'type', 'pan', 'zoom', 'zoom-short', 'auto-zoom' );
 128+ }
 129+
 130+ /**
 131+ * Changes the map type name into the corresponding Yahoo! Maps API identifier.
 132+ *
 133+ * @param string $type
 134+ *
 135+ * @return string
 136+ */
 137+ public static function setYMapType( &$type ) {
 138+ $type = self::$mapTypes[ $type ];
 139+ }
 140+
 141+ /**
 142+ * Changes the map type names into the corresponding Yahoo! Maps API identifiers.
 143+ *
 144+ * @param array $types
 145+ *
 146+ * @return array
 147+ */
 148+ public static function setYMapTypes( array &$types ) {
 149+ for ( $i = count( $types ) - 1; $i >= 0; $i-- ) {
 150+ $types[$i] = self::$mapTypes[ $types[$i] ];
 151+ }
 152+ }
 153+
 154+ /**
 155+ * Add references to the Yahoo! Maps API and required JS file to the provided output
 156+ *
 157+ * @param string $output
 158+ */
 159+ public static function addYMapDependencies( &$output ) {
 160+ global $wgJsMimeType;
 161+ global $egYahooMapsKey, $egMapsScriptPath, $egYahooMapsOnThisPage, $egMapsStyleVersion, $egMapsJsExt;
 162+
 163+ if ( empty( $egYahooMapsOnThisPage ) ) {
 164+ $egYahooMapsOnThisPage = 0;
 165+
 166+ $dir = dirname( __FILE__ );
 167+
 168+ $output .= "<script type='$wgJsMimeType' src='http://api.maps.yahoo.com/ajaxymap?v=3.8&amp;appid=$egYahooMapsKey'></script>
 169+ <script type='$wgJsMimeType' src='$egMapsScriptPath/Services/YahooMaps/YahooMapFunctions{$egMapsJsExt}?$egMapsStyleVersion'></script>";
 170+ }
 171+ }
 172+
 173+}
\ No newline at end of file
Index: trunk/extensions/Maps/Services/OpenLayers/Maps_OpenLayersDispPoint.php
@@ -0,0 +1,84 @@
 2+<?php
 3+
 4+/**
 5+ * File holding the MapsOpenLayersDispPoint class.
 6+ *
 7+ * @file Maps_OpenLayersDispPoint.php
 8+ * @ingroup MapsOpenLayers
 9+ *
 10+ * @author Jeroen De Dauw
 11+ */
 12+
 13+if ( !defined( 'MEDIAWIKI' ) ) {
 14+ die( 'Not an entry point.' );
 15+}
 16+
 17+/**
 18+ * Class for handling the display_point(s) parser functions with OpenLayers.
 19+ *
 20+ * @author Jeroen De Dauw
 21+ */
 22+class MapsOpenLayersDispPoint extends MapsBasePointMap {
 23+
 24+ public $serviceName = MapsOpenLayers::SERVICE_NAME;
 25+
 26+ protected $markerStringFormat = 'getOLMarkerData(lon, lat, \'title\', \'label\', "icon")';
 27+
 28+ protected function getDefaultZoom() {
 29+ global $egMapsOpenLayersZoom;
 30+ return $egMapsOpenLayersZoom;
 31+ }
 32+
 33+ /**
 34+ * @see MapsBaseMap::doMapServiceLoad()
 35+ *
 36+ */
 37+ protected function doMapServiceLoad() {
 38+ global $egOpenLayersOnThisPage;
 39+
 40+ MapsOpenLayers::addOLDependencies( $this->output );
 41+ $egOpenLayersOnThisPage++;
 42+
 43+ $this->elementNr = $egOpenLayersOnThisPage;
 44+ }
 45+
 46+ /**
 47+ * @see MapsBaseMap::addSpecificMapHTML()
 48+ *
 49+ */
 50+ public function addSpecificMapHTML( Parser $parser ) {
 51+ global $egMapsOpenLayersPrefix, $egOpenLayersOnThisPage;
 52+
 53+ $layerItems = MapsOpenLayers::createLayersStringAndLoadDependencies( $this->output, $this->layers );
 54+
 55+ $mapName = $egMapsOpenLayersPrefix . '_' . $egOpenLayersOnThisPage;
 56+
 57+ $this->output .= Html::element(
 58+ 'div',
 59+ array(
 60+ 'id' => $mapName,
 61+ 'style' => "width: $this->width; height: $this->height; background-color: #cccccc;",
 62+ ),
 63+ wfMsg('maps-loading-map')
 64+ );
 65+
 66+ $parser->getOutput()->addHeadItem(
 67+ Html::inlineScript( <<<EOT
 68+addOnloadHook(
 69+ function() {
 70+ initOpenLayer(
 71+ '$mapName',
 72+ $this->centreLon,
 73+ $this->centreLat,
 74+ $this->zoom,
 75+ [$layerItems],
 76+ [$this->controls],
 77+ [$this->markerString]
 78+ );
 79+ }
 80+);
 81+EOT
 82+ ) );
 83+ }
 84+
 85+}
\ No newline at end of file
Index: trunk/extensions/Maps/Services/OpenLayers/OpenLayerFunctions.js
@@ -0,0 +1,171 @@
 2+ /**
 3+ * Javascript functions for Open Layers functionallity in Maps and it's extensions
 4+ *
 5+ * @file OpenLayerFunctions.js
 6+ * @ingroup MapsOpenLayers
 7+ *
 8+ * @author Jeroen De Dauw
 9+ */
 10+
 11+/**
 12+ * Creates and initializes an OpenLayers map.
 13+ * The resulting map is returned by the function but no further handling is required in most cases.
 14+ */
 15+function initOpenLayer(mapName, lon, lat, zoom, mapTypes, controls, marker_data){
 16+
 17+ // Create a new OpenLayers map with without any controls on it.
 18+ var mapOptions = {
 19+ projection: new OpenLayers.Projection("EPSG:900913"),
 20+ displayProjection: new OpenLayers.Projection("EPSG:4326"),
 21+ units: "m",
 22+ numZoomLevels: 18,
 23+ maxResolution: 156543.0339,
 24+ maxExtent: new OpenLayers.Bounds(-20037508, -20037508, 20037508, 20037508.34),
 25+ controls: []
 26+ };
 27+
 28+ var mapElement = document.getElementById(mapName);
 29+
 30+ // Remove the loading map message.
 31+ mapElement.innerHTML = '';
 32+
 33+ var map = new OpenLayers.Map(mapName, mapOptions);
 34+
 35+ // Add the controls.
 36+ for (i in controls) {
 37+
 38+ // If a string is provided, find the correct name for the control, and use eval to create the object itself.
 39+ if (typeof controls[i] == 'string') {
 40+ if (controls[i].toLowerCase() == 'autopanzoom') {
 41+ if (mapElement.offsetHeight > 140) controls[i] = mapElement.offsetHeight > 320 ? 'panzoombar' : 'panzoom';
 42+ }
 43+
 44+ control = getValidControlName(controls[i]);
 45+
 46+ if (control) {
 47+ eval(' map.addControl( new OpenLayers.Control.' + control + '() ); ');
 48+ }
 49+ }
 50+ else {
 51+ map.addControl(controls[i]); // If a control is provided, instead a string, just add it.
 52+ controls[i].activate(); // And activate it.
 53+ }
 54+
 55+ }
 56+
 57+ // Add the base layers.
 58+ for (i in mapTypes) map.addLayer(mapTypes[i]);
 59+
 60+ // Layer to hold the markers.
 61+ var markerLayer = new OpenLayers.Layer.Markers('Markers');
 62+ markerLayer.id= 'markerLayer';
 63+ map.addLayer(markerLayer);
 64+
 65+ var centerIsSet = lon != null && lat != null;
 66+
 67+ var bounds = null;
 68+
 69+ if (marker_data.length > 1 && (!centerIsSet || zoom == null)) {
 70+ bounds = new OpenLayers.Bounds();
 71+ }
 72+
 73+ for (i in marker_data) {
 74+ marker_data[i].lonlat.transform(new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913"));
 75+ if (bounds != null) bounds.extend(marker_data[i].lonlat); // Extend the bounds when no center is set.
 76+ markerLayer.addMarker(getOLMarker(markerLayer, marker_data[i], map.getProjectionObject())); // Create and add the marker.
 77+ }
 78+
 79+ if (bounds != null) map.zoomToExtent(bounds); // If a bounds object has been created, use it to set the zoom and center.
 80+
 81+ if (centerIsSet) { // When the center is provided, set it.
 82+ var centre = new OpenLayers.LonLat(lon, lat);
 83+ centre.transform(new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913"));
 84+ map.setCenter(centre);
 85+ }
 86+
 87+ if (zoom != null) map.zoomTo(zoom); // When the zoom is provided, set it.
 88+
 89+ return map;
 90+}
 91+
 92+/**
 93+ * Gets a valid control name (with excat lower and upper case letters),
 94+ * or returns false when the control is not allowed.
 95+ */
 96+function getValidControlName(control) {
 97+ var OLControls = ['ArgParser', 'Attribution', 'Button', 'DragFeature', 'DragPan',
 98+ 'DrawFeature', 'EditingToolbar', 'GetFeature', 'KeyboardDefaults', 'LayerSwitcher',
 99+ 'Measure', 'ModifyFeature', 'MouseDefaults', 'MousePosition', 'MouseToolbar',
 100+ 'Navigation', 'NavigationHistory', 'NavToolbar', 'OverviewMap', 'Pan',
 101+ 'Panel', 'PanPanel', 'PanZoom', 'PanZoomBar', 'Permalink',
 102+ 'Scale', 'ScaleLine', 'SelectFeature', 'Snapping', 'Split',
 103+ 'WMSGetFeatureInfo', 'ZoomBox', 'ZoomIn', 'ZoomOut', 'ZoomPanel',
 104+ 'ZoomToMaxExtent'];
 105+
 106+ for (i in OLControls) {
 107+ if (control == OLControls[i].toLowerCase()) {
 108+ return OLControls[i];
 109+ }
 110+ }
 111+
 112+ return false;
 113+}
 114+
 115+function getOLMarker(markerLayer, markerData, projectionObject) {
 116+ var marker;
 117+
 118+ if (markerData.icon != "") {
 119+ //var iconSize = new OpenLayers.Size(10,17);
 120+ //var iconOffset = new OpenLayers.Pixel(-(iconSize.w/2), -iconSize.h);
 121+ marker = new OpenLayers.Marker(markerData.lonlat, new OpenLayers.Icon(markerData.icon)); // , iconSize, iconOffset
 122+ } else {
 123+ marker = new OpenLayers.Marker(markerData.lonlat);
 124+ }
 125+
 126+ if (markerData.title.length + markerData.label.length > 0 ) {
 127+
 128+ // This is the handler for the mousedown event on the marker, and displays the popup.
 129+ marker.events.register('mousedown', marker,
 130+ function(evt) {
 131+ var popup = new OpenLayers.Feature(markerLayer, markerData.lonlat).createPopup(true);
 132+
 133+ if (markerData.title.length > 0 && markerData.label.length > 0) { // Add the title and label to the popup text.
 134+ popup.setContentHTML('<b>' + markerData.title + '</b><hr />' + markerData.label);
 135+ }
 136+ else {
 137+ popup.setContentHTML(markerData.title + markerData.label);
 138+ }
 139+
 140+ popup.setOpacity(0.85);
 141+ markerLayer.map.addPopup(popup);
 142+ OpenLayers.Event.stop(evt); // Stop the event.
 143+ }
 144+ );
 145+
 146+ }
 147+
 148+ return marker;
 149+}
 150+
 151+function getOLMarkerData(lon, lat, title, label, icon) {
 152+ lonLat = new OpenLayers.LonLat(lon, lat);
 153+ return {
 154+ lonlat: lonLat,
 155+ title: title,
 156+ label: label,
 157+ icon: icon
 158+ };
 159+}
 160+
 161+function initOLSettings(minWidth, minHeight) {
 162+ OpenLayers.IMAGE_RELOAD_ATTEMPTS = 3;
 163+ OpenLayers.Util.onImageLoadErrorColor = 'transparent';
 164+ OpenLayers.Feature.prototype.popupClass = OpenLayers.Class(
 165+ OpenLayers.Popup.FramedCloud,
 166+ {
 167+ 'autoSize': true,
 168+ 'minSize': new OpenLayers.Size(minWidth, minHeight)
 169+ }
 170+ );
 171+}
 172+
Index: trunk/extensions/Maps/Services/OpenLayers/OpenLayerFunctions.min.js
@@ -0,0 +1,18 @@
 2+function initOpenLayer(mapName,lon,lat,zoom,mapTypes,controls,marker_data,height){var mapOptions={projection:new OpenLayers.Projection("EPSG:900913"),displayProjection:new OpenLayers.Projection("EPSG:4326"),units:"m",numZoomLevels:18,maxResolution:156543.0339,maxExtent:new OpenLayers.Bounds(-20037508,-20037508,20037508,2.003750834E7),controls:[]};var map=new OpenLayers.Map(mapName,mapOptions);for(i in controls)if(typeof controls[i]=="string"){if(controls[i].toLowerCase()=="autopanzoom")if(height>
 3+140)controls[i]=height>320?"panzoombar":"panzoom";control=getValidControlName(controls[i]);if(control)eval(" map.addControl( new OpenLayers.Control."+control+"() ); ")}else{map.addControl(controls[i]);controls[i].activate()}addMapBaseLayers(map,mapTypes);var markerLayer=new OpenLayers.Layer.Markers("Markers");markerLayer.id="markerLayer";map.addLayer(markerLayer);var centerIsSet=lon!=null&&lat!=null;var bounds=null;if(marker_data.length>1&&(!centerIsSet||zoom==null))bounds=new OpenLayers.Bounds;for(i in marker_data){marker_data[i].lonlat.transform(new OpenLayers.Projection("EPSG:4326"),
 4+new OpenLayers.Projection("EPSG:900913"));if(bounds!=null)bounds.extend(marker_data[i].lonlat);markerLayer.addMarker(getOLMarker(markerLayer,marker_data[i],map.getProjectionObject()))}if(bounds!=null)map.zoomToExtent(bounds);if(centerIsSet){var centre=new OpenLayers.LonLat(lon,lat);centre.transform(new OpenLayers.Projection("EPSG:4326"),new OpenLayers.Projection("EPSG:900913"));map.setCenter(centre)}if(zoom!=null)map.zoomTo(zoom);return map}
 5+function getValidControlName(control){var OLControls=["ArgParser","Attribution","Button","DragFeature","DragPan","DrawFeature","EditingToolbar","GetFeature","KeyboardDefaults","LayerSwitcher","Measure","ModifyFeature","MouseDefaults","MousePosition","MouseToolbar","Navigation","NavigationHistory","NavToolbar","OverviewMap","Pan","Panel","PanPanel","PanZoom","PanZoomBar","Permalink","Scale","ScaleLine","SelectFeature","Snapping","Split","WMSGetFeatureInfo","ZoomBox","ZoomIn","ZoomOut","ZoomPanel",
 6+"ZoomToMaxExtent"];for(i in OLControls)if(control==OLControls[i].toLowerCase())return OLControls[i];return false}
 7+function addMapBaseLayers(map,mapTypes){var googleAPILoaded=typeof G_NORMAL_MAP!="undefined";var shownApiError=false;var usedNor=false;var usedSat=false;var usedHyb=false;var usedPhy=false;var usedBingNor=false;var usedBingHyb=false;var usedBingSat=false;var usedYahooNor=false;var usedYahooHyb=false;var usedYahooSat=false;var usedOLWMS=false;var usedOSMnik=false;var usedOSMcycle=false;var usedOSMarender=false;var usedNasa=false;var isDefaultBaseLayer=false;for(i in mapTypes){var newLayer=null;switch(mapTypes[i]){case "google":case "google-normal":case "google-satellite":case "google-hybrid":case "google-physical":if(googleAPILoaded)switch(mapTypes[i]){case "google-normal":if(!usedNor){newLayer=
 8+new OpenLayers.Layer.Google("Google Streets",{sphericalMercator:true});usedNor=true}break;case "google-satellite":if(!usedSat){newLayer=new OpenLayers.Layer.Google("Google Satellite",{type:G_SATELLITE_MAP,sphericalMercator:true});usedSat=true}break;case "google-hybrid":if(!usedHyb){newLayer=new OpenLayers.Layer.Google("Google Hybrid",{type:G_HYBRID_MAP,sphericalMercator:true});usedHyb=true}break;case "google-physical":if(!usedPhy){newLayer=new OpenLayers.Layer.Google("Google Physical",{type:G_PHYSICAL_MAP,
 9+sphericalMercator:true});usedPhy=true}break;case "google":if(!usedNor){map.addLayer(new OpenLayers.Layer.Google("Google Streets",{sphericalMercator:true}));usedNor=true}if(!usedSat){map.addLayer(new OpenLayers.Layer.Google("Google Satellite",{type:G_SATELLITE_MAP,sphericalMercator:true}));usedSat=true}if(!usedHyb){map.addLayer(new OpenLayers.Layer.Google("Google Hybrid",{type:G_HYBRID_MAP,sphericalMercator:true}));usedHyb=true}if(!usedPhy){map.addLayer(new OpenLayers.Layer.Google("Google Physical",
 10+{type:G_PHYSICAL_MAP,sphericalMercator:true}));usedPhy=true}break}else if(!shownApiError){window.alert("Please enter your Google Maps API key to use the Google Maps layers");shownApiError=true}break;case "bing":case "virtual-earth":if(!usedBingNor){map.addLayer(new OpenLayers.Layer.VirtualEarth("Bing Streets",{type:VEMapStyle.Shaded,sphericalMercator:true}));usedBingNor=true}if(!usedBingSat){map.addLayer(new OpenLayers.Layer.VirtualEarth("Bing Satellite",{type:VEMapStyle.Aerial,sphericalMercator:true}));
 11+usedBingSat=true}if(!usedBingHyb){map.addLayer(new OpenLayers.Layer.VirtualEarth("Bing Hybrid",{type:VEMapStyle.Hybrid,sphericalMercator:true}));usedBingHyb=true}break;case "bing-normal":if(!usedBingNor){newLayer=new OpenLayers.Layer.VirtualEarth("Bing Streets",{type:VEMapStyle.Shaded,sphericalMercator:true});usedBingNor=true}case "bing-satellite":if(!usedBingSat){newLayer=new OpenLayers.Layer.VirtualEarth("Bing Satellite",{type:VEMapStyle.Aerial,sphericalMercator:true});usedBingSat=true}case "bing-hybrid":if(!usedBingHyb){newLayer=
 12+new OpenLayers.Layer.VirtualEarth("Bing Hybrid",{type:VEMapStyle.Hybrid,sphericalMercator:true});usedBingHyb=true}case "yahoo":if(!usedYahooNor){map.addLayer(new OpenLayers.Layer.Yahoo("Yahoo! Streets"),{sphericalMercator:true});usedYahooNor=true}if(!usedYahooSat){map.addLayer(new OpenLayers.Layer.Yahoo("Yahoo! Satellite",{type:YAHOO_MAP_SAT,sphericalMercator:true}));usedYahooSat=true}if(!usedYahooHyb){map.addLayer(new OpenLayers.Layer.Yahoo("Yahoo! Hybrid",{type:YAHOO_MAP_HYB,sphericalMercator:true}));
 13+usedYahooHyb=true}break;case "yahoo-normal":if(!usedYahooNor){newLayer=new OpenLayers.Layer.Yahoo("Yahoo! Streets",{sphericalMercator:true});usedYahooNor=true}break;case "yahoo-satellite":if(!usedYahooSat){newLayer=new OpenLayers.Layer.Yahoo("Yahoo! Satellite",{type:YAHOO_MAP_SAT,sphericalMercator:true});usedYahooSat=true}break;case "yahoo-hybrid":if(!usedYahooHyb){newLayer=new OpenLayers.Layer.Yahoo("Yahoo! Hybrid",{type:YAHOO_MAP_HYB,sphericalMercator:true});usedYahooHyb=true}break;case "openlayers":case "open-layers":if(!usedOLWMS){newLayer=
 14+new OpenLayers.Layer.WMS("OpenLayers WMS","http://labs.metacarta.com/wms/vmap0",{layers:"basic",sphericalMercator:true});usedOLWMS=true}break;case "nasa":if(!usedNasa){newLayer=new OpenLayers.Layer.WMS("NASA Global Mosaic","http://t1.hypercube.telascience.org/cgi-bin/landsat7",{layers:"landsat7",sphericalMercator:true});usedNasa=true}break;case "osm":case "openstreetmap":if(!usedOSMarender){map.addLayer(new OpenLayers.Layer.OSM.Osmarender("OSM arender"));usedOSMarender=true}if(!usedOSMnik){map.addLayer(new OpenLayers.Layer.OSM.Mapnik("OSM Mapnik"),
 15+{sphericalMercator:true});usedOSMnik=true}if(!usedOSMcycle){map.addLayer(new OpenLayers.Layer.OSM.CycleMap("OSM Cycle Map"),{sphericalMercator:true});usedOSMcycle=true}break;case "osmarender":if(!usedOSMarender){newLayer=new OpenLayers.Layer.OSM.Osmarender("OSM arender");usedOSMarender=true}break;case "osm-nik":case "osm-mapnik":if(!usedOSMnik){newLayer=new OpenLayers.Layer.OSM.Mapnik("OSM Mapnik");usedOSMnik=true}break;case "osm-cycle":case "osm-cyclemap":if(!usedOSMcycle){newLayer=new OpenLayers.Layer.OSM.CycleMap("OSM Cycle Map");
 16+usedOSMcycle=true}break}if(newLayer!=null)map.addLayer(newLayer)}return map}
 17+function getOLMarker(markerLayer,markerData,projectionObject){var marker;if(markerData.icon!="")marker=new OpenLayers.Marker(markerData.lonlat,new OpenLayers.Icon(markerData.icon));else marker=new OpenLayers.Marker(markerData.lonlat);if(markerData.title.length+markerData.label.length>0)marker.events.register("mousedown",marker,function(evt){var popup=(new OpenLayers.Feature(markerLayer,markerData.lonlat)).createPopup(true);if(markerData.title.length>0&&markerData.label.length>0)popup.setContentHTML("<b>"+
 18+markerData.title+"</b><hr />"+markerData.label);else popup.setContentHTML(markerData.title+markerData.label);popup.setOpacity(0.85);markerLayer.map.addPopup(popup);OpenLayers.Event.stop(evt)});return marker}function getOLMarkerData(lon,lat,title,label,icon){lonLat=new OpenLayers.LonLat(lon,lat);return{lonlat:lonLat,title:title,label:label,icon:icon}}
 19+function initOLSettings(minWidth,minHeight){OpenLayers.IMAGE_RELOAD_ATTEMPTS=3;OpenLayers.Util.onImageLoadErrorColor="transparent";OpenLayers.Feature.prototype.popupClass=OpenLayers.Class(OpenLayers.Popup.FramedCloud,{autoSize:true,minSize:new OpenLayers.Size(minWidth,minHeight)})};
\ No newline at end of file
Index: trunk/extensions/Maps/Services/OpenLayers/Maps_OpenLayersDispMap.php
@@ -0,0 +1,75 @@
 2+<?php
 3+
 4+/**
 5+ * Class for handling the display_map parser function with OpenLayers
 6+ *
 7+ * @file Maps_OpenLayersDispMap.php
 8+ * @ingroup MapsOpenLayers
 9+ *
 10+ * @author Jeroen De Dauw
 11+ */
 12+
 13+if ( !defined( 'MEDIAWIKI' ) ) {
 14+ die( 'Not an entry point.' );
 15+}
 16+
 17+class MapsOpenLayersDispMap extends MapsBaseMap {
 18+
 19+ public $serviceName = MapsOpenLayers::SERVICE_NAME;
 20+
 21+ protected function getDefaultZoom() {
 22+ global $egMapsOpenLayersZoom;
 23+ return $egMapsOpenLayersZoom;
 24+ }
 25+
 26+ /**
 27+ * @see MapsBaseMap::doMapServiceLoad()
 28+ */
 29+ protected function doMapServiceLoad() {
 30+ global $egOpenLayersOnThisPage;
 31+
 32+ MapsOpenLayers::addOLDependencies( $this->output );
 33+ $egOpenLayersOnThisPage++;
 34+
 35+ $this->elementNr = $egOpenLayersOnThisPage;
 36+ }
 37+
 38+ /**
 39+ * @see MapsBaseMap::addSpecificMapHTML()
 40+ */
 41+ public function addSpecificMapHTML( Parser $parser ) {
 42+ global $egMapsOpenLayersPrefix, $egOpenLayersOnThisPage;
 43+
 44+ $layerItems = MapsOpenLayers::createLayersStringAndLoadDependencies( $this->output, $this->layers );
 45+
 46+ $mapName = $egMapsOpenLayersPrefix . '_' . $egOpenLayersOnThisPage;
 47+
 48+ $this->output .= Html::element(
 49+ 'div',
 50+ array(
 51+ 'id' => $mapName,
 52+ 'style' => "width: $this->width; height: $this->height; background-color: #cccccc;",
 53+ ),
 54+ wfMsg('maps-loading-map')
 55+ );
 56+
 57+ $parser->getOutput()->addHeadItem(
 58+ Html::inlineScript( <<<EOT
 59+addOnloadHook(
 60+ function() {
 61+ initOpenLayer(
 62+ '$mapName',
 63+ $this->centreLon,
 64+ $this->centreLat,
 65+ $this->zoom,
 66+ [$layerItems],
 67+ [$this->controls],
 68+ []
 69+ );
 70+ }
 71+);
 72+EOT
 73+ ) );
 74+ }
 75+
 76+}
\ No newline at end of file
Index: trunk/extensions/Maps/Services/OpenLayers/Maps_OpenLayers.php
@@ -0,0 +1,207 @@
 2+<?php
 3+
 4+/**
 5+ * This groupe contains all OpenLayers related files of the Maps extension.
 6+ *
 7+ * @defgroup MapsOpenLayers OpenLayers
 8+ * @ingroup Maps
 9+ */
 10+
 11+/**
 12+ * This file holds the general information for the OpenLayers service
 13+ *
 14+ * @file Maps_OpenLayers.php
 15+ * @ingroup MapsOpenLayers
 16+ *
 17+ * @author Jeroen De Dauw
 18+ */
 19+
 20+if ( !defined( 'MEDIAWIKI' ) ) {
 21+ die( 'Not an entry point.' );
 22+}
 23+
 24+$wgAutoloadClasses['MapsOpenLayers'] = dirname( __FILE__ ) . '/Maps_OpenLayers.php';
 25+
 26+$wgHooks['MappingServiceLoad'][] = 'MapsOpenLayers::initialize';
 27+
 28+$wgAutoloadClasses['MapsOpenLayersDispMap'] = dirname( __FILE__ ) . '/Maps_OpenLayersDispMap.php';
 29+$wgAutoloadClasses['MapsOpenLayersDispPoint'] = dirname( __FILE__ ) . '/Maps_OpenLayersDispPoint.php';
 30+
 31+$egMapsServices[MapsOpenLayers::SERVICE_NAME] = array(
 32+ 'aliases' => array( 'layers', 'openlayer' ),
 33+ 'features' => array(
 34+ 'display_point' => 'MapsOpenLayersDispPoint',
 35+ 'display_map' => 'MapsOpenLayersDispMap',
 36+ )
 37+);
 38+
 39+/**
 40+ * Class for OpenLayers initialization.
 41+ *
 42+ * @ingroup MapsOpenLayers
 43+ *
 44+ * @author Jeroen De Dauw
 45+ */
 46+class MapsOpenLayers {
 47+
 48+ const SERVICE_NAME = 'openlayers';
 49+
 50+ public static function initialize() {
 51+ global $wgAutoloadClasses, $egMapsServices, $egMapsOLLoadedLayers;
 52+
 53+ $egMapsOLLoadedLayers = array();
 54+
 55+ self::initializeParams();
 56+
 57+ Validator::addOutputFormat( 'olgroups', array( __CLASS__, 'unpackLayerGroups' ) );
 58+
 59+ return true;
 60+ }
 61+
 62+ private static function initializeParams() {
 63+ global $egMapsServices, $egMapsOLLayers, $egMapsOLControls, $egMapsOpenLayersZoom;
 64+
 65+ $egMapsServices[self::SERVICE_NAME]['parameters'] = array(
 66+ 'controls' => array(
 67+ 'type' => array( 'string', 'list' ),
 68+ 'criteria' => array(
 69+ 'in_array' => self::getControlNames()
 70+ ),
 71+ 'default' => $egMapsOLControls,
 72+ 'output-type' => array( 'list', ',', '\'' )
 73+ ),
 74+ 'layers' => array(
 75+ 'type' => array( 'string', 'list' ),
 76+ 'criteria' => array(
 77+ 'in_array' => self::getLayerNames( true )
 78+ ),
 79+ 'default' => $egMapsOLLayers,
 80+ 'output-types' => array(
 81+ 'unique_items',
 82+ 'olgroups',
 83+ array( 'filtered_array', self::getLayerNames() ),
 84+ )
 85+ ),
 86+ );
 87+
 88+ $egMapsServices[self::SERVICE_NAME]['parameters']['zoom']['criteria']['in_range'] = array( 0, 19 );
 89+ }
 90+
 91+ /**
 92+ * Returns the names of all supported controls.
 93+ * This data is a copy of the one used to actually translate the names
 94+ * into the controls, since this resides client side, in OpenLayerFunctions.js.
 95+ *
 96+ * @return array
 97+ */
 98+ public static function getControlNames() {
 99+ return array(
 100+ 'argparser', 'attribution', 'button', 'dragfeature', 'dragpan',
 101+ 'drawfeature', 'editingtoolbar', 'getfeature', 'keyboarddefaults', 'layerswitcher',
 102+ 'measure', 'modifyfeature', 'mousedefaults', 'mouseposition', 'mousetoolbar',
 103+ 'navigation', 'navigationhistory', 'navtoolbar', 'overviewmap', 'pan',
 104+ 'panel', 'panpanel', 'panzoom', 'panzoombar', 'autopanzoom', 'permalink',
 105+ 'scale', 'scaleline', 'selectfeature', 'snapping', 'split',
 106+ 'wmsgetfeatureinfo', 'zoombox', 'zoomin', 'zoomout', 'zoompanel',
 107+ 'zoomtomaxextent'
 108+ );
 109+ }
 110+
 111+ /**
 112+ * Returns the names of all supported layers.
 113+ *
 114+ * @return array
 115+ */
 116+ public static function getLayerNames( $includeGroups = false ) {
 117+ global $egMapsOLAvailableLayers, $egMapsOLLayerGroups;
 118+ $keys = array_keys( $egMapsOLAvailableLayers );
 119+ if ( $includeGroups ) $keys = array_merge( $keys, array_keys( $egMapsOLLayerGroups ) );
 120+ return $keys;
 121+ }
 122+
 123+ /**
 124+ * If this is the first open layers map on the page, load the API, styles and extra JS functions
 125+ *
 126+ * @param string $output
 127+ */
 128+ public static function addOLDependencies( &$output ) {
 129+ global $wgJsMimeType;
 130+ global $egOpenLayersOnThisPage, $egMapsStyleVersion, $egMapsJsExt, $egMapsScriptPath;
 131+
 132+ if ( empty( $egOpenLayersOnThisPage ) ) {
 133+ $egOpenLayersOnThisPage = 0;
 134+
 135+ $dir = dirname( __FILE__ );
 136+
 137+ $output .= "<link rel='stylesheet' href='$egMapsScriptPath/Services/OpenLayers/OpenLayers/theme/default/style.css' type='text/css' />
 138+ <script type='$wgJsMimeType' src='$egMapsScriptPath/Services/OpenLayers/OpenLayers/OpenLayers.js'></script>
 139+ <script type='$wgJsMimeType' src='$egMapsScriptPath/Services/OpenLayers/OpenLayerFunctions{$egMapsJsExt}?$egMapsStyleVersion'></script>
 140+ <script type='$wgJsMimeType'>initOLSettings(200, 100);</script>\n";
 141+ }
 142+ }
 143+
 144+ /**
 145+ * Build up a csv string with the layers, to be outputted as a JS array
 146+ *
 147+ * @param string $output
 148+ * @param string $layers
 149+ * @return csv string
 150+ */
 151+ public static function createLayersStringAndLoadDependencies( &$output, array $layers ) {
 152+ global $egMapsOLAvailableLayers;
 153+ $layerStr = array();
 154+
 155+ foreach ( $layers as $layer ) {
 156+ self::loadDependencyWhenNeeded( $output, $layer );
 157+ $layerStr[] = is_array( $egMapsOLAvailableLayers[$layer] ) ? $egMapsOLAvailableLayers[$layer][0] : $egMapsOLAvailableLayers[$layer];
 158+ }
 159+
 160+ return 'new ' . implode( ',new ', $layerStr );
 161+ }
 162+
 163+ /**
 164+ * Load the dependencies of a layer if they are not loaded yet.
 165+ *
 166+ * @param string $output The output to which the html to load the dependencies needs to be added
 167+ * @param string $layer The layer to check (and load the dependencies for
 168+ */
 169+ public static function loadDependencyWhenNeeded( &$output, $layer ) {
 170+ global $wgJsMimeType;
 171+ global $egMapsOLAvailableLayers, $egMapsOLLayerDependencies, $egMapsOLLoadedLayers;
 172+
 173+ // Check if there is a dependency refered by the layer definition.
 174+ if ( is_array( $egMapsOLAvailableLayers[$layer] )
 175+ && count( $egMapsOLAvailableLayers[$layer] ) > 1
 176+ && array_key_exists( $egMapsOLAvailableLayers[$layer][1], $egMapsOLLayerDependencies )
 177+ && !in_array( $egMapsOLAvailableLayers[$layer][1], $egMapsOLLoadedLayers ) ) {
 178+ // Add the dependency to the output.
 179+ $output .= $egMapsOLLayerDependencies[$egMapsOLAvailableLayers[$layer][1]];
 180+ // Register that it's added so it does not get done multiple times.
 181+ $egMapsOLLoadedLayers[] = $egMapsOLAvailableLayers[$layer][1];
 182+ }
 183+ }
 184+
 185+ /**
 186+ * Removed the layer groups from the layer list, and adds their members back in.
 187+ *
 188+ * @param array $layers
 189+ */
 190+ public static function unpackLayerGroups( array &$layers ) {
 191+ global $egMapsOLLayerGroups;
 192+
 193+ $unpacked = array();
 194+
 195+ foreach ( $layers as $layerOrGroup ) {
 196+ if ( array_key_exists( $layerOrGroup, $egMapsOLLayerGroups ) ) {
 197+ $unpacked = array_merge( $unpacked, $egMapsOLLayerGroups[$layerOrGroup] );
 198+ }
 199+ else {
 200+ $unpacked[] = $layerOrGroup;
 201+ }
 202+ }
 203+
 204+ $layers = $unpacked;
 205+ }
 206+
 207+}
 208+
\ No newline at end of file
Index: trunk/extensions/Maps/Services/OpenStreetMap/Maps_OSMCgiBin.php
@@ -0,0 +1,180 @@
 2+<?php
 3+
 4+/**
 5+ * File holding the MapsOSMCgiBin class.
 6+ *
 7+ * @file Maps_OSMCgiBin.php
 8+ * @ingroup MapsOpenStreetMap
 9+ *
 10+ * @author Ævar Arnfjörð Bjarmason
 11+ * @author Jeroen De Dauw
 12+ */
 13+
 14+if ( !defined( 'MEDIAWIKI' ) ) {
 15+ die( 'Not an entry point.' );
 16+}
 17+
 18+/**
 19+ * A class for static image requests.
 20+ *
 21+ * @author Ævar Arnfjörð Bjarmason
 22+ * @author Jeroen De Dauw
 23+ */
 24+
 25+final class MapsOSMCgiBin {
 26+ private $lat;
 27+ private $lon;
 28+ private $zoom;
 29+ private $width;
 30+ private $height;
 31+ private $url;
 32+
 33+ /** borrowed from OpenLayers.DOTS_PER_UNIT */
 34+ private static $INCHES_PER_UNIT = array (
 35+ 'dd' => 4374754,
 36+ 'm' => 39.3701
 37+ );
 38+
 39+ /** borrowed from OpenLayers.DOTS_PER_INCH */
 40+ private static $DOTS_PER_INCH = 72;
 41+
 42+ /** pixel size in meters */
 43+ private static $PIXEL_SIZE = 0.00028;
 44+
 45+ /**
 46+ * Constructor
 47+ */
 48+ public function __construct( $lat, $lon, $zoom, $width, $height, $lang, $options ) {
 49+ $this->lat = $lat;
 50+ $this->lon = $lon;
 51+ $this->zoom = $zoom;
 52+ $this->width = $width;
 53+ $this->height = $height;
 54+ $this->lang = $lang;
 55+ $this->options = $options;
 56+
 57+ self::initResolutionsAndScales();
 58+ self::setBounds();
 59+ }
 60+
 61+ /**
 62+ * Returns the image url.
 63+ *
 64+ * @return string
 65+ */
 66+ public function getUrl() {
 67+ $urlElements = array();
 68+
 69+ $urlElements[] = $this->options['base_url'];
 70+ $urlElements[] = '?bbox=';
 71+ $urlElements[] = implode( ',', $this->bounds );
 72+ $urlElements[] = '&amp;scale=';
 73+ $urlElements[] = $this->scale;
 74+ $urlElements[] = '&amp;format=';
 75+ $urlElements[] = $this->options['format'];
 76+ $urlElements[] = '&amp;locale=';
 77+ $urlElements[] = $this->lang;
 78+
 79+ if ( array_key_exists( 'maptype', $this->options ) ) {
 80+ $urlElements[] = '&amp;maptype=';
 81+ $urlElements[] = $this->options['maptype'];
 82+ }
 83+
 84+ return implode( '', $urlElements );
 85+ }
 86+
 87+ /**
 88+ * This sets the map bounds
 89+ */
 90+ public function setBounds() {
 91+
 92+ /* Determine scale and map bounds for static render request */
 93+ $resolution = $this->resolutions[round( $this->zoom )];
 94+ $this->scale = self::getScaleFromResolution( $resolution );
 95+
 96+ /*
 97+ * Calculate width for Mapnik output using a standard pixel size of 0.00028m
 98+ * @see http://trac.mapnik.org/wiki/ScaleAndPpi
 99+ */
 100+ $w_deg = $this->width * self::$PIXEL_SIZE * $this->scale;
 101+ $h_deg = $this->height * self::$PIXEL_SIZE * $this->scale;
 102+
 103+ $center = array( $this->lon, $this->lat );
 104+ if ( $this->options['sphericalMercator'] ) {
 105+ // Calculate bounds within a spherical mercator projection if that is what the scale is based on.
 106+ $mercatorCenter = self::forwardMercator( $center );
 107+
 108+ $this->bounds = self::inverseMercator(
 109+ array(
 110+ $mercatorCenter[0] - $w_deg / 2,
 111+ $mercatorCenter[1] - $h_deg / 2,
 112+ $mercatorCenter[0] + $w_deg / 2,
 113+ $mercatorCenter[1] + $h_deg / 2
 114+ )
 115+ );
 116+ }
 117+ else {
 118+ // Calculate bounds within WGS84
 119+ $this->bounds = array(
 120+ $center[0] - $w_deg / 2,
 121+ $center[1] - $h_deg / 2,
 122+ $center[0] + $w_deg / 2,
 123+ $center[1] + $h_deg / 2
 124+ );
 125+ }
 126+ }
 127+
 128+ /**
 129+ * Borrowed from OpenLayers.Util.getScaleFromResolution
 130+ */
 131+ protected function getScaleFromResolution( $resolution ) {
 132+ return $resolution * self::$INCHES_PER_UNIT[$this->options['unit']] * self::$DOTS_PER_INCH;
 133+ }
 134+
 135+ /**
 136+ * Determines resolutions and scales based on a maximum resolution and number of zoom levels
 137+ * Borrowed from OpenLayers.Layer.initResolutions
 138+ */
 139+ protected function initResolutionsAndScales() {
 140+ $this->resolutions = array();
 141+ $base = 2;
 142+
 143+ for ( $i = 0; $i < $this->options['numZoomLevels']; $i++ ) {
 144+ $this->resolutions[$i] = $this->options['maxResolution'] / pow( $base, $i );
 145+ $this->scales[$i] = $this->getScaleFromResolution( $this->resolutions[$i] );
 146+ }
 147+ }
 148+
 149+ /**
 150+ * Convert from WGS84 to spherical mercator.
 151+ */
 152+ private static function forwardMercator( array $lonlat ) {
 153+ for ( $i = 0; $i < count( $lonlat ); $i += 2 ) {
 154+ /* lon */
 155+ $lonlat[$i] = $lonlat[$i] * ( 2 * M_PI * 6378137 / 2.0 ) / 180.0;
 156+
 157+ /* lat */
 158+ $lonlat[$i + 1] = log( tan( ( 90 + $lonlat[$i + 1] ) * M_PI / 360.0 ) ) / ( M_PI / 180.0 );
 159+ $lonlat[$i + 1] = $lonlat[$i + 1] * ( 2 * M_PI * 6378137 / 2.0 ) / 180.0;
 160+ }
 161+ return $lonlat;
 162+ }
 163+
 164+ /**
 165+ * Convert from spherical mercator to WGS84.
 166+ */
 167+ private static function inverseMercator( array $lonlat ) {
 168+ for ( $i = 0; $i < count( $lonlat ); $i += 2 ) {
 169+ /* lon */
 170+ $lonlat[$i] = $lonlat[$i] / ( ( 2 * M_PI * 6378137 / 2.0 ) / 180.0 );
 171+
 172+ /* lat */
 173+ $lonlat[$i + 1] = $lonlat[$i + 1] / ( ( 2 * M_PI * 6378137 / 2.0 ) / 180.0 );
 174+ $lonlat[$i + 1] = 180.0 / M_PI * ( 2 * atan( exp( $lonlat[$i + 1] * M_PI / 180.0 ) ) - M_PI / 2 );
 175+ }
 176+
 177+ return $lonlat;
 178+ }
 179+
 180+}
 181+
Index: trunk/extensions/Maps/Services/OpenStreetMap/Maps_OSMDispMap.php
@@ -0,0 +1,166 @@
 2+<?php
 3+
 4+/**
 5+ * Class for handling the display_map parser function with OSM.
 6+ *
 7+ * @file Maps_OSMDispMap.php
 8+ * @ingroup MapsOpenStreetMap
 9+ *
 10+ * @author Jeroen De Dauw
 11+ */
 12+
 13+if ( !defined( 'MEDIAWIKI' ) ) {
 14+ die( 'Not an entry point.' );
 15+}
 16+
 17+class MapsOSMDispMap extends MapsBaseMap {
 18+
 19+ public $serviceName = MapsOSM::SERVICE_NAME;
 20+
 21+ /**
 22+ * @see MapsBaseMap::setMapSettings()
 23+ *
 24+ */
 25+ protected function setMapSettings() {
 26+ global $egMapsOSMZoom, $egMapsOSMPrefix, $egMapsOSMStaticAsDefault, $egMapsOSMStaticActivatable;
 27+
 28+ $this->elementNamePrefix = $egMapsOSMPrefix;
 29+ $this->defaultZoom = $egMapsOSMZoom;
 30+
 31+ $modes = MapsOSM::getModeNames();
 32+
 33+ $this->spesificParameters = array(
 34+ 'static' => array(
 35+ 'type' => 'boolean',
 36+ 'default' => $egMapsOSMStaticAsDefault,
 37+ 'output-type' => 'boolean'
 38+ ),
 39+ 'mode' => array(
 40+ 'criteria' => array(
 41+ 'in_array' => $modes
 42+ ),
 43+ 'default' => $modes[0]
 44+ ),
 45+ 'activatable' => array(
 46+ 'type' => 'boolean',
 47+ 'default' => $egMapsOSMStaticActivatable,
 48+ 'output-type' => 'boolean'
 49+ ),
 50+ );
 51+ }
 52+
 53+ /**
 54+ * @see MapsBaseMap::doMapServiceLoad()
 55+ *
 56+ */
 57+ protected function doMapServiceLoad() {
 58+ global $egOSMMapsOnThisPage;
 59+
 60+ MapsOSM::addOSMDependencies( $this->output );
 61+ $egOSMMapsOnThisPage++;
 62+
 63+ $this->elementNr = $egOSMMapsOnThisPage;
 64+ }
 65+
 66+ /**
 67+ * @see MapsBaseMap::addSpecificMapHTML()
 68+ *
 69+ */
 70+ public function addSpecificMapHTML( Parser $parser ) {
 71+ $parser->getOutput()->addHeadItem(
 72+ Html::inlineScript( <<<EOT
 73+addOnloadHook(
 74+ function() {
 75+ slippymaps['$this->mapName'] = new slippymap_map(
 76+ '$this->mapName',
 77+ {
 78+ mode: '$this->mode',
 79+ layer: 'osm-like',
 80+ locale: '$this->lang',
 81+ lat: $this->centreLat,
 82+ lon: $this->centreLon,
 83+ zoom: $this->zoom,
 84+ markers: [],
 85+ controls: [$this->controls]
 86+ }
 87+ );
 88+ }
 89+);
 90+EOT
 91+ ) );
 92+
 93+ $this->output .= $this->static ? $this->getStaticMap() : $this->getDynamicMap();
 94+ }
 95+
 96+ /**
 97+ * Returns html for a dynamic map.
 98+ *
 99+ * @return string
 100+ */
 101+ private function getDynamicMap() {
 102+ global $wgOut;
 103+
 104+ $wgOut->addInlineScript( <<<EOT
 105+addOnloadHook(
 106+ function() {
 107+ slippymaps['$this->mapName'].init();
 108+ }
 109+);
 110+EOT
 111+ );
 112+
 113+ return Html::element(
 114+ 'div',
 115+ array(
 116+ 'id' => $this->mapName,
 117+ 'style' => "width: $this->width; height: $this->height; background-color: #cccccc;",
 118+ ),
 119+ wfMsg('maps-loading-map')
 120+ );
 121+ }
 122+
 123+ /**
 124+ * Returns html for a static map.
 125+ *
 126+ * @return string
 127+ */
 128+ private function getStaticMap() {
 129+ $mode = MapsOSM::getModeData( $this->mode );
 130+
 131+ $staticType = $mode['handler'];
 132+ $staticOptions = $mode['options'];
 133+
 134+ $static = new $staticType( $this->centreLat, $this->centreLon, $this->zoom, $this->width, $this->height, $this->lang, $staticOptions );
 135+ $rendering_url = $static->getUrl();
 136+
 137+ $alt = wfMsg( 'maps_centred_on', $this->centreLat, $this->centreLon );
 138+ $title = $this->activatable ? wfMsg( 'maps_click_to_activate' ) : $alt;
 139+
 140+ $image = array(
 141+ 'class' => 'mapPreview',
 142+ 'src' => $rendering_url,
 143+ 'width' => $this->width,
 144+ 'height' => $this->height,
 145+ 'alt' => $alt,
 146+ 'title' => $title,
 147+ );
 148+
 149+ if ( $this->activatable ) {
 150+ $image['onclick'] = "slippymaps['$this->mapName'].init();";
 151+ }
 152+
 153+ return Html::element(
 154+ 'div',
 155+ array(
 156+ 'id' => $this->mapName,
 157+ 'style' => "width: $this->width; height: $this->height; background-color: #cccccc;",
 158+ ),
 159+ Html::element(
 160+ 'img',
 161+ $image
 162+ )
 163+ );
 164+ }
 165+
 166+}
 167+
Index: trunk/extensions/Maps/Services/OpenStreetMap/OSMFunctions.js
@@ -0,0 +1,202 @@
 2+/*
 3+ * @file OSMFunctions.js
 4+ * @ingroup MapsOpenStreetMap
 5+ *
 6+ * @author Harry Wood, Jens Frank, Grant Slater, Raymond Spekking, Jeroen De Dauw and others
 7+ *
 8+ * @description
 9+ *
 10+ * Javascript functions for OSM optimized Open Layers functionallity in Maps and it's extensions
 11+ *
 12+ * This defines what happens when <slippymap> tag is placed in the wikitext
 13+ *
 14+ * We show a map based on the lat/lon/zoom data passed in. This extension brings in
 15+ * the OpenLayers javascript, to show a slippy map.
 16+ *
 17+ * Usage example:
 18+ * <slippymap lat=51.485 lon=-0.15 z=11 w=300 h=200 layer=osmarender></slippymap>
 19+ *
 20+ * Tile images are not cached local to the wiki.
 21+ * To acheive this (remove the OSM dependency) you might set up a squid proxy,
 22+ * and modify the requests URLs here accordingly.
 23+ *
 24+ * This file should be placed in the mediawiki 'extensions' directory
 25+ * ...and then it needs to be 'included' within LocalSettings.php
 26+ *
 27+ * This program is free software; you can redistribute it and/or modify
 28+ * it under the terms of the GNU General Public License as published by
 29+ * the Free Software Foundation; either version 2 of the License, or
 30+ * (at your option) any later version.
 31+ *
 32+ * This program is distributed in the hope that it will be useful,
 33+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 34+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 35+ * GNU General Public License for more details.
 36+ *
 37+ * You should have received a copy of the GNU General Public License
 38+ * along with this program; if not, write to the Free Software
 39+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 40+ *
 41+ */
 42+
 43+var slippymaps = new Array();
 44+var mapId = 0;
 45+var layer = null;
 46+
 47+/**
 48+ * Gets a valid control name (with excat lower and upper case letters),
 49+ * or returns false when the control is not allowed.
 50+ */
 51+function getValidControlName(control) {
 52+ var OLControls = ['ArgParser', 'Attribution', 'Button', 'DragFeature', 'DragPan',
 53+ 'DrawFeature', 'EditingToolbar', 'GetFeature', 'KeyboardDefaults', 'LayerSwitcher',
 54+ 'Measure', 'ModifyFeature', 'MouseDefaults', 'MousePosition', 'MouseToolbar',
 55+ 'Navigation', 'NavigationHistory', 'NavToolbar', 'OverviewMap', 'Pan',
 56+ 'Panel', 'PanPanel', 'PanZoom', 'PanZoomBar', 'Permalink',
 57+ 'Scale', 'ScaleLine', 'SelectFeature', 'Snapping', 'Split',
 58+ 'WMSGetFeatureInfo', 'ZoomBox', 'ZoomIn', 'ZoomOut', 'ZoomPanel',
 59+ 'ZoomToMaxExtent'];
 60+
 61+ for (i in OLControls) {
 62+ if (control == OLControls[i].toLowerCase()) {
 63+ return OLControls[i];
 64+ }
 65+ }
 66+
 67+ return false;
 68+}
 69+
 70+function slippymap_map(mapId, mapParams) {
 71+ var self = this;
 72+ this.mapId = mapId;
 73+
 74+ for (key in mapParams)
 75+ this[key] = mapParams[key];
 76+
 77+ // Add the controls
 78+ this.mapOptions = {controls: []};
 79+
 80+ for (i in this.controls) {
 81+ if (typeof controls[i] == 'string') {
 82+ if (this.controls[i].toLowerCase() == 'autopanzoom') {
 83+ //if (this.height > 140) this.controls[i] = this.height > 320 ? 'panzoombar' : 'panzoom';
 84+ }
 85+
 86+ control = getValidControlName(this.controls[i]);
 87+
 88+ if (control) {
 89+ eval(' this.mapOptions.controls.push( new OpenLayers.Control.' + control + '() ); ');
 90+ }
 91+ }
 92+ else {
 93+ this.mapOptions.controls.push(controls[i]); // If a control is provided, instead a string, just add it.
 94+ controls[i].activate(); // And activate it.
 95+ }
 96+ }
 97+}
 98+
 99+slippymap_map.prototype.init = function() {
 100+ /* Swap out against the preview image */
 101+ var previewImage = document.getElementById(this.mapId + '-preview');
 102+ if (previewImage)
 103+ previewImage.style.display = 'none';
 104+
 105+ this.map = this.osm_create(this.mapId, this.lon, this.lat, this.zoom, this.initializedContols);
 106+
 107+ var centerIsSet = this.lon != null && this.lat != null;
 108+
 109+ var bounds = null;
 110+
 111+ if (this.markers.length > 0) {
 112+ var markerLayer = new OpenLayers.Layer.Markers('Markers');
 113+ markerLayer.id= 'markerLayer';
 114+ this.map.addLayer(markerLayer);
 115+
 116+ if (this.markers.length > 1 && (!centerIsSet || this.zoom == null)) {
 117+ bounds = new OpenLayers.Bounds();
 118+ }
 119+
 120+ for (i in this.markers) {
 121+ this.markers[i].lonlat.transform(new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913"));
 122+ if (bounds != null) bounds.extend(this.markers[i].lonlat); // Extend the bounds when no center is set
 123+ markerLayer.addMarker(getOSMMarker(markerLayer, this.markers[i], this.map.getProjectionObject())); // Create and add the marker
 124+ }
 125+
 126+ }
 127+
 128+ if (bounds != null) map.zoomToExtent(bounds); // If a bounds object has been created, use it to set the zoom and center
 129+
 130+ if (centerIsSet) { // When the center is provided, set it
 131+ var centre = new OpenLayers.LonLat(this.lon, this.lat);
 132+ centre.transform(new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913"));
 133+ this.map.setCenter(centre);
 134+ }
 135+
 136+ if (this.zoom != null) this.map.zoomTo(this.zoom); // When the zoom is provided, set it
 137+}
 138+
 139+slippymap_map.prototype.osm_create = function(mapId, lon, lat, zoom, initializedContols) {
 140+ var osmLayer;
 141+ var map = new OpenLayers.Map(mapId, this.mapOptions /* all provided for by OSM.js */);
 142+
 143+ if (initializedContols) {
 144+ for (i in initializedContols) {
 145+ map.addControl(initializedContols[i]);
 146+ initializedContols[i].activate();
 147+ }
 148+ }
 149+
 150+ if (this.layer == 'osm-like') {
 151+ osmLayer = new OpenLayers.Layer.OSM("OpenStreetMap", 'http://cassini.toolserver.org/tiles/osm-like/' + this.locale + '/${z}/${x}/${y}.png');
 152+ }
 153+
 154+ map.addLayers([osmLayer]);
 155+ map.setCenter(new OpenLayers.LonLat(lon, lat).transform(new OpenLayers.Projection('EPSG:4326'), map.getProjectionObject()), zoom);
 156+ return map;
 157+}
 158+
 159+function getOSMMarkerData(lon, lat, title, label, icon) {
 160+ lonLat = new OpenLayers.LonLat(lon, lat);
 161+ return {
 162+ lonlat: lonLat,
 163+ title: title,
 164+ label: label,
 165+ icon: icon
 166+ };
 167+}
 168+
 169+
 170+function getOSMMarker(markerLayer, markerData, projectionObject) {
 171+ var marker;
 172+
 173+ if (markerData.icon != '') {
 174+ marker = new OpenLayers.Marker(markerData.lonlat, new OpenLayers.Icon(markerData.icon));
 175+ } else {
 176+ marker = new OpenLayers.Marker(markerData.lonlat);
 177+ }
 178+
 179+ if (markerData.title.length + markerData.label.length > 0 ) {
 180+
 181+ // This is the handler for the mousedown event on the marker, and displays the popup
 182+ marker.events.register('mousedown', marker,
 183+ function(evt) {
 184+ var popup = new OpenLayers.Feature(markerLayer, markerData.lonlat).createPopup(true);
 185+
 186+ if (markerData.title.length > 0 && markerData.label.length > 0) { // Add the title and label to the popup text
 187+ popup.setContentHTML('<b>' + markerData.title + "</b><hr />" + markerData.label);
 188+ }
 189+ else {
 190+ popup.setContentHTML(markerData.title + markerData.label);
 191+ }
 192+
 193+ popup.setOpacity(0.85);
 194+ markerLayer.map.addPopup(popup);
 195+ OpenLayers.Event.stop(evt); // Stop the event
 196+ }
 197+ );
 198+
 199+ }
 200+
 201+ return marker;
 202+}
 203+
Index: trunk/extensions/Maps/Services/OpenStreetMap/Maps_OSM.php
@@ -0,0 +1,166 @@
 2+<?php
 3+
 4+/**
 5+ * This groupe contains all OpenStreetMap related files of the Maps extension.
 6+ *
 7+ * @defgroup MapsOpenStreetMap OpenStreetMap
 8+ * @ingroup Maps
 9+ */
 10+
 11+/**
 12+ * This file holds the general information for the OSM optimized OpenLayers service
 13+ *
 14+ * @file Maps_OSM.php
 15+ * @ingroup MapsOpenStreetMap
 16+ *
 17+ * @author Jeroen De Dauw
 18+ *
 19+ * FIXME: this file has not been changed to work with 0.6
 20+ */
 21+
 22+if ( !defined( 'MEDIAWIKI' ) ) {
 23+ die( 'Not an entry point.' );
 24+}
 25+
 26+$egMapsServices['osm'] = array(
 27+ 'pf' => array(
 28+ 'display_point' => array( 'class' => 'MapsOSMDispPoint', 'file' => 'OpenStreetMap/Maps_OSMDispPoint.php', 'local' => true ),
 29+ 'display_map' => array( 'class' => 'MapsOSMDispMap', 'file' => 'OpenStreetMap/Maps_OSMDispMap.php', 'local' => true ),
 30+ ),
 31+ 'classes' => array(
 32+ array( 'class' => 'MapsOSM', 'file' => 'OpenStreetMap/Maps_OSM.php', 'local' => true ),
 33+ array( 'class' => 'MapsOSMCgiBin', 'file' => 'OpenStreetMap/Maps_OSMCgiBin.php', 'local' => true ),
 34+ ),
 35+ 'aliases' => array( 'openstreetmap', 'openstreetmaps' ),
 36+ );
 37+
 38+/**
 39+ * Class for OpenStreetMap initialization.
 40+ *
 41+ * @ingroup MapsOpenStreetMap
 42+ *
 43+ * @author Jeroen De Dauw
 44+ */
 45+class MapsOSM {
 46+
 47+ const SERVICE_NAME = 'osm';
 48+
 49+ public static function initialize() {
 50+ self::initializeParams();
 51+ }
 52+
 53+ private static function initializeParams() {
 54+ global $wgLang;
 55+ global $egMapsServices, $egMapsOSMZoom, $egMapsOSMControls;
 56+
 57+ $egMapsServices[self::SERVICE_NAME]['parameters']['zoom']['default'] = $egMapsOSMZoom;
 58+ $egMapsServices[self::SERVICE_NAME]['parameters']['zoom']['criteria']['in_range'] = array( 0, 19 );
 59+
 60+ $egMapsServices[self::SERVICE_NAME]['parameters'] = array(
 61+ 'controls' => array(
 62+ 'type' => array( 'string', 'list' ),
 63+ 'criteria' => array(
 64+ 'in_array' => self::getControlNames()
 65+ ),
 66+ 'default' => $egMapsOSMControls,
 67+ 'output-type' => array( 'list', ',', '\'' )
 68+ ),
 69+ 'lang' => array(
 70+ 'aliases' => array( 'locale', 'language' ),
 71+ 'criteria' => array(
 72+ 'in_array' => array_keys( Language::getLanguageNames( false ) )
 73+ ),
 74+ 'default' => $wgLang->getCode()
 75+ ),
 76+ );
 77+ }
 78+
 79+ /**
 80+ * Returns the names of all supported controls.
 81+ * This data is a copy of the one used to actually translate the names
 82+ * into the controls, since this resides client side, in OSMFunctions.js.
 83+ *
 84+ * @return array
 85+ */
 86+ public static function getControlNames() {
 87+ return array(
 88+ 'ArgParser', 'Attribution', 'Button', 'DragFeature', 'DragPan',
 89+ 'DrawFeature', 'EditingToolbar', 'GetFeature', 'KeyboardDefaults', 'LayerSwitcher',
 90+ 'Measure', 'ModifyFeature', 'MouseDefaults', 'MousePosition', 'MouseToolbar',
 91+ 'Navigation', 'NavigationHistory', 'NavToolbar', 'OverviewMap', 'Pan',
 92+ 'Panel', 'PanPanel', 'PanZoom', 'PanZoomBar', 'AutoPanZoom', 'Permalink',
 93+ 'Scale', 'ScaleLine', 'SelectFeature', 'Snapping', 'Split',
 94+ 'WMSGetFeatureInfo', 'ZoomBox', 'ZoomIn', 'ZoomOut', 'ZoomPanel',
 95+ 'ZoomToMaxExtent'
 96+ );
 97+ }
 98+
 99+ private static $modes = array(
 100+ 'osm-wm' => array(
 101+ 'handler' => 'MapsOSMCgiBin',
 102+ 'options' => array(
 103+ 'base_url' => 'http://cassini.toolserver.org/cgi-bin/export',
 104+
 105+ 'format' => 'png',
 106+ 'numZoomLevels' => 16,
 107+ 'maxResolution' => 156543.0339,
 108+ 'unit' => 'm',
 109+ 'sphericalMercator' => true,
 110+
 111+ 'maptype' => 'osm-like'
 112+ ),
 113+ ),
 114+
 115+ 'osm' => array(
 116+ 'handler' => 'MapsOSMCgiBin',
 117+ 'options' => array(
 118+ 'base_url' => 'http://tile.openstreetmap.org/cgi-bin/export',
 119+
 120+ 'format' => 'png',
 121+ 'numZoomLevels' => 16,
 122+ 'maxResolution' => 156543.0339,
 123+ 'unit' => 'm',
 124+ 'sphericalMercator' => true
 125+ ),
 126+ ),
 127+ );
 128+
 129+ /**
 130+ * Returns an array containing the names of all modes.
 131+ *
 132+ * @return array
 133+ */
 134+ public static function getModeNames() {
 135+ return array_keys( self::$modes );
 136+ }
 137+
 138+ /**
 139+ * Returns the data of a mode.
 140+ *
 141+ * @param string $modeName
 142+ * @return array
 143+ */
 144+ public static function getModeData( $modeName ) {
 145+ return self::$modes[$modeName];
 146+ }
 147+
 148+ /**
 149+ * If this is the first OSM map on the page, load the OpenLayers API, OSM styles and extra JS functions
 150+ *
 151+ * @param string $output
 152+ */
 153+ public static function addOSMDependencies( &$output ) {
 154+ global $wgJsMimeType;
 155+ global $egOSMMapsOnThisPage, $egMapsScriptPath, $egMapsStyleVersion, $egMapsJsExt;
 156+
 157+ if ( empty( $egOSMMapsOnThisPage ) ) {
 158+ $egOSMMapsOnThisPage = 0;
 159+
 160+ $output .= "<link rel='stylesheet' href='$egMapsScriptPath/OpenLayers/OpenLayers/theme/default/style.css' type='text/css' />
 161+ <script type='$wgJsMimeType' src='$egMapsScriptPath/OpenLayers/OpenLayers/OpenLayers.js'></script>
 162+ <script type='$wgJsMimeType' src='$egMapsScriptPath/OpenStreetMap/OSMFunctions{$egMapsJsExt}?$egMapsStyleVersion'></script>
 163+ <script type='$wgJsMimeType'>slippymaps = Array();</script>\n";
 164+ }
 165+ }
 166+
 167+}
\ No newline at end of file
Index: trunk/extensions/Maps/Services/OpenStreetMap/OSMFunctions.min.js
@@ -0,0 +1,21 @@
 2+var slippymaps=new Array();var mapId=0;var layer=null;if(false){addOnloadHook(slippymap_init);}
 3+function slippymap_init(){for(keyName in slippymaps){slippymaps[keyName].init();}}
 4+function getValidControlName(control){var OLControls=['ArgParser','Attribution','Button','DragFeature','DragPan','DrawFeature','EditingToolbar','GetFeature','KeyboardDefaults','LayerSwitcher','Measure','ModifyFeature','MouseDefaults','MousePosition','MouseToolbar','Navigation','NavigationHistory','NavToolbar','OverviewMap','Pan','Panel','PanPanel','PanZoom','PanZoomBar','Permalink','Scale','ScaleLine','SelectFeature','Snapping','Split','WMSGetFeatureInfo','ZoomBox','ZoomIn','ZoomOut','ZoomPanel','ZoomToMaxExtent'];for(i in OLControls){if(control==OLControls[i].toLowerCase()){return OLControls[i];}}
 5+return false;}
 6+function slippymap_map(mapId,mapParams){var self=this;this.mapId=mapId;for(key in mapParams)
 7+this[key]=mapParams[key];this.mapOptions={controls:[]};for(i in this.controls){if(this.controls[i].toLowerCase()=='autopanzoom'){if(this.height>140)this.controls[i]=this.height>320?'panzoombar':'panzoom';}
 8+control=getValidControlName(this.controls[i]);if(control){eval(' this.mapOptions.controls.push( new OpenLayers.Control.'+control+'() ); ');}}}
 9+slippymap_map.prototype.init=function(){var previewImage=document.getElementById(this.mapId+'-preview');if(previewImage)
 10+previewImage.style.display='none';this.map=this.osm_create(this.mapId,this.lon,this.lat,this.zoom,this.initializedContols);var centerIsSet=this.lon!=null&&this.lat!=null;var bounds=null;if(this.markers.length>0){var markerLayer=new OpenLayers.Layer.Markers('Markers');markerLayer.id='markerLayer';this.map.addLayer(markerLayer);if(this.markers.length>1&&(!centerIsSet||this.zoom==null)){bounds=new OpenLayers.Bounds();}
 11+for(i in this.markers){this.markers[i].lonlat.transform(new OpenLayers.Projection("EPSG:4326"),new OpenLayers.Projection("EPSG:900913"));if(bounds!=null)bounds.extend(this.markers[i].lonlat);markerLayer.addMarker(getOSMMarker(markerLayer,this.markers[i],this.map.getProjectionObject()));}}
 12+if(bounds!=null)map.zoomToExtent(bounds);if(centerIsSet){var centre=new OpenLayers.LonLat(this.lon,this.lat);centre.transform(new OpenLayers.Projection("EPSG:4326"),new OpenLayers.Projection("EPSG:900913"));this.map.setCenter(centre);}
 13+if(this.zoom!=null)this.map.zoomTo(this.zoom);}
 14+slippymap_map.prototype.osm_create=function(mapId,lon,lat,zoom,initializedContols){var osmLayer;var map=new OpenLayers.Map(mapId,this.mapOptions);if(initializedContols){for(i in initializedContols){map.addControl(initializedContols[i]);initializedContols[i].activate();}}
 15+if(this.layer=='osm-like'){osmLayer=new OpenLayers.Layer.OSM("OpenStreetMap",'http://cassini.toolserver.org/tiles/osm-like/'+this.locale+'/${z}/${x}/${y}.png');}
 16+map.addLayers([osmLayer]);map.setCenter(new OpenLayers.LonLat(lon,lat).transform(new OpenLayers.Projection('EPSG:4326'),map.getProjectionObject()),zoom);return map;}
 17+function getOSMMarkerData(lon,lat,title,label,icon){lonLat=new OpenLayers.LonLat(lon,lat);return{lonlat:lonLat,title:title,label:label,icon:icon};}
 18+function getOSMMarker(markerLayer,markerData,projectionObject){var marker;if(markerData.icon!=''){marker=new OpenLayers.Marker(markerData.lonlat,new OpenLayers.Icon(markerData.icon));}else{marker=new OpenLayers.Marker(markerData.lonlat);}
 19+if(markerData.title.length+markerData.label.length>0){marker.events.register('mousedown',marker,function(evt){var popup=new OpenLayers.Feature(markerLayer,markerData.lonlat).createPopup(true);if(markerData.title.length>0&&markerData.label.length>0){popup.setContentHTML('<b>'+markerData.title+"</b><hr />"+markerData.label);}
 20+else{popup.setContentHTML(markerData.title+markerData.label);}
 21+popup.setOpacity(0.85);markerLayer.map.addPopup(popup);OpenLayers.Event.stop(evt);});}
 22+return marker;}
\ No newline at end of file
Index: trunk/extensions/Maps/Services/OpenStreetMap/Maps_OSMDispPoint.php
@@ -0,0 +1,87 @@
 2+<?php
 3+
 4+/**
 5+ * File holding the MapsOSMDispPoint class.
 6+ *
 7+ * @file Maps_OSMDispPoint.php
 8+ * @ingroup MapsOpenStreetMap
 9+ *
 10+ * @author Jeroen De Dauw
 11+ */
 12+
 13+if ( !defined( 'MEDIAWIKI' ) ) {
 14+ die( 'Not an entry point.' );
 15+}
 16+
 17+/**
 18+ * Class for handling the display_point(s) parser functions with OSM.
 19+ *
 20+ * @author Jeroen De Dauw
 21+ */
 22+class MapsOSMDispPoint extends MapsBasePointMap {
 23+
 24+ public $serviceName = MapsOSM::SERVICE_NAME;
 25+
 26+ /**
 27+ * @see MapsBaseMap::setMapSettings()
 28+ *
 29+ */
 30+ protected function setMapSettings() {
 31+ global $egMapsOSMZoom, $egMapsOSMPrefix;
 32+
 33+ $this->elementNamePrefix = $egMapsOSMPrefix;
 34+ $this->defaultZoom = $egMapsOSMZoom;
 35+
 36+ $this->markerStringFormat = 'getOSMMarkerData(lat, lon, \'title\', \'label\', "icon")';
 37+ }
 38+
 39+ /**
 40+ * @see MapsBaseMap::doMapServiceLoad()
 41+ *
 42+ */
 43+ protected function doMapServiceLoad() {
 44+ global $egOSMMapsOnThisPage;
 45+
 46+ MapsOSM::addOSMDependencies( $this->output );
 47+ $egOSMMapsOnThisPage++;
 48+
 49+ $this->elementNr = $egOSMMapsOnThisPage;
 50+ }
 51+
 52+ /**
 53+ * @see MapsBaseMap::addSpecificMapHTML()
 54+ *
 55+ */
 56+ public function addSpecificMapHTML( Parser $parser ) {
 57+ $parser->getOutput()->addHeadItem(
 58+ Html::inlineScript( <<<EOT
 59+addOnloadHook(
 60+ function() {
 61+ slippymaps['$this->mapName'] = new slippymap_map(
 62+ '$this->mapName',
 63+ {
 64+ layer: 'osm-like',
 65+ locale: '$this->lang',
 66+ lat: $this->centreLat,
 67+ lon: $this->centreLon,
 68+ zoom: $this->zoom,
 69+ markers: [$this->markerString],
 70+ controls: [$this->controls]
 71+ }
 72+ );
 73+ slippymaps['$this->mapName'].init();
 74+ }
 75+);
 76+EOT
 77+ ) );
 78+
 79+ $this->output .= Html::element(
 80+ 'div',
 81+ array(
 82+ 'id' => $this->mapName,
 83+ 'style' => "width: $this->width; height: $this->height; background-color: #cccccc;",
 84+ ),
 85+ wfMsg('maps-loading-map')
 86+ );
 87+ }
 88+}
\ No newline at end of file
Index: trunk/extensions/Maps/Services/GoogleMaps/GoogleMapFunctions.min.js
@@ -0,0 +1,20 @@
 2+var GOverlays=[new GLayer("com.panoramio.all"),new GLayer("com.youtube.all"),new GLayer("org.wikipedia.en"),new GLayer("com.google.webcams")];function createGMarker(point,title,label,icon){var marker;if(icon!=''){var iconObj=new GIcon(G_DEFAULT_ICON);iconObj.image=icon;marker=new GMarker(point,{icon:iconObj});}else{marker=new GMarker(point);}
 3+if((title+label).length>0){var bothTxtAreSet=title.length>0&&label.length>0;var popupText=bothTxtAreSet?'<b>'+title+'</b><hr />'+label:title+label;popupText='<div style="overflow:auto;max-height:150px;">'+popupText+'</div>';GEvent.addListener(marker,'click',function(){marker.openInfoWindowHtml(popupText,{maxWidth:350});});}
 4+return marker;}
 5+function initializeGoogleMap(mapName,mapOptions,markers){if(GBrowserIsCompatible()){mapOptions.centre=(mapOptions.lat!=null&&mapOptions.lon!=null)?new GLatLng(mapOptions.lat,mapOptions.lon):null;mapOptions.size=new GSize(mapOptions.width,mapOptions.height);return createGoogleMap(mapName,mapOptions,markers);}
 6+else{return false;}}
 7+function createGoogleMap(mapName,mapOptions,markers){var mapElement=document.getElementById(mapName);var typesContainType=false;for(var i=0;i<mapOptions.types.length;i++){if(mapOptions.types[i]==mapOptions.type)typesContainType=true;}
 8+if(!typesContainType)mapOptions.types.push(mapOptions.type);var map=new GMap2(mapElement,{size:mapOptions.size,mapTypes:mapOptions.types});map.name=mapName;map.setMapType(mapOptions.type);for(i in mapOptions.controls){if(mapOptions.controls[i].toLowerCase()=='auto'){if(mapOptions.height>75)mapOptions.controls[i]=mapOptions.height>320?'large':'small';}
 9+switch(mapOptions.controls[i]){case'large':map.addControl(new GLargeMapControl3D());break;case'small':map.addControl(new GSmallZoomControl3D());break;case'large-original':map.addControl(new GLargeMapControl());break;case'small-original':map.addControl(new GSmallMapControl());break;case'zoom':map.addControl(new GSmallZoomControl());break;case'type':map.addControl(new GMapTypeControl());break;case'type-menu':map.addControl(new GMenuMapTypeControl());break;case'overlays':map.addControl(new MoreControl());break;case'overview':case'overview-map':map.addControl(new GOverviewMapControl());break;case'scale':map.addControl(new GScaleControl());break;case'nav-label':case'nav':map.addControl(new GNavLabelControl());break;}}
 10+var bounds=((mapOptions.zoom==null||mapOptions.centre==null)&&markers.length>1)?new GLatLngBounds():null;for(i in markers){var marker=markers[i];map.addOverlay(createGMarker(marker.point,marker.title,marker.label,marker.icon));if(bounds!=null)bounds.extend(marker.point);}
 11+if(bounds!=null){map.setCenter(bounds.getCenter(),map.getBoundsZoomLevel(bounds));}
 12+if(mapOptions.centre!=null)map.setCenter(mapOptions.centre);if(mapOptions.zoom!=null)map.setZoom(mapOptions.zoom);if(mapOptions.scrollWheelZoom)map.enableScrollWheelZoom();map.enableContinuousZoom();if(!window.GMaps)window.GMaps=new Object;eval("window.GMaps."+mapName+" = map;");return map;}
 13+function getGMarkerData(lat,lon,title,label,icon){return{point:new GLatLng(lat,lon),title:title,label:label,icon:icon};}
 14+function setupCheckboxShiftClick(){return true;}
 15+function MoreControl(){};MoreControl.prototype=new GControl();MoreControl.prototype.initialize=function(map){this.map=map;var more=document.getElementById(map.name+"-outer-more");var buttonDiv=document.createElement("div");buttonDiv.id=map.name+"-more-button";buttonDiv.title="Show/Hide Overlays";buttonDiv.style.border="1px solid black";buttonDiv.style.width="86px";var textDiv=document.createElement("div");textDiv.id=map.name+"-inner-more";textDiv.setAttribute('class','inner-more');textDiv.appendChild(document.createTextNode("Overlays"));buttonDiv.appendChild(textDiv);more.onmouseover=showGLayerbox;more.onmouseout=setGLayerboxClose;more.insertBefore(buttonDiv,document.getElementById(map.name+"-more-box").parentNode);map.getContainer().appendChild(more);return more;};MoreControl.prototype.getDefaultPosition=function(){return new GControlPosition(G_ANCHOR_TOP_RIGHT,new GSize(7,35));};function checkGChecked(mapName){var boxes=document.getElementsByName(mapName+"-overlay-box");for(var i=0;i<boxes.length;i++){if(boxes[i].checked)return true;}
 16+return false;}
 17+function showGLayerbox(){var mapName=this.id.split('-')[0];eval("if(window.timer_"+mapName+") clearTimeout(timer_"+mapName+");");document.getElementById(mapName+"-more-box").style.display="block";var button=document.getElementById(mapName+"-inner-more");button.style.borderBottomWidth="4px";button.style.borderBottomColor="white";}
 18+function setGLayerboxClose(){var mapName=this.id.split('-')[0];var layerbox=document.getElementById(mapName+"-more-box");var button=document.getElementById(mapName+"-inner-more");var bottomColor=checkGChecked(mapName)?"#6495ed":"#c0c0c0";eval("timer_"+mapName+" = window.setTimeout(function() { layerbox.style.display = 'none'; button.style.borderBottomWidth = '1px'; button.style.borderBottomColor = bottomColor; }, 400);");}
 19+function switchGLayer(map,checked,layer){var layerbox=document.getElementById(map.name+"-more-box");var button=document.getElementById(map.name+"-inner-more");if(checked){map.addOverlay(layer);}
 20+else{map.removeOverlay(layer);}}
 21+function initiateGOverlay(elementId,mapName,urlNr){document.getElementById(elementId).checked=true;switchGLayer(GMaps[mapName],true,GOverlays[urlNr]);}
\ No newline at end of file
Index: trunk/extensions/Maps/Services/GoogleMaps/Maps_GoogleMapsDispMap.php
@@ -0,0 +1,100 @@
 2+<?php
 3+
 4+/**
 5+ * Class for handling the display_map parser function with Google Maps
 6+ *
 7+ * @file Maps_GoogleMapsDispMap.php
 8+ * @ingroup MapsGoogleMaps
 9+ *
 10+ * @author Jeroen De Dauw
 11+ */
 12+
 13+if ( !defined( 'MEDIAWIKI' ) ) {
 14+ die( 'Not an entry point.' );
 15+}
 16+
 17+/**
 18+ * Class for handling the display_map parser functions with Google Maps.
 19+ *
 20+ * @ingroup MapsGoogleMaps
 21+ *
 22+ * @author Jeroen De Dauw
 23+ */
 24+final class MapsGoogleMapsDispMap extends MapsBaseMap {
 25+
 26+ public $serviceName = MapsGoogleMaps::SERVICE_NAME;
 27+
 28+ protected function getDefaultZoom() {
 29+ global $egMapsGoogleMapsZoom;
 30+ return $egMapsGoogleMapsZoom;
 31+ }
 32+
 33+ public function getSpecificParameterInfo() {
 34+ global $egMapsGMapOverlays;
 35+ $this->spesificParameters = array(
 36+ 'overlays' => array(
 37+ 'type' => array( 'string', 'list' ),
 38+ 'criteria' => array(
 39+ 'is_google_overlay' => array()
 40+ ),
 41+ 'default' => $egMapsGMapOverlays,
 42+ ),
 43+ );
 44+ return $this->spesificParameters;
 45+ }
 46+
 47+ /**
 48+ * @see MapsBaseMap::doMapServiceLoad()
 49+ */
 50+ public function doMapServiceLoad() {
 51+ global $egGoogleMapsOnThisPage;
 52+
 53+ MapsGoogleMaps::addGMapDependencies( $this->output );
 54+ $egGoogleMapsOnThisPage++;
 55+
 56+ $this->elementNr = $egGoogleMapsOnThisPage;
 57+ }
 58+
 59+ /**
 60+ * @see MapsBaseMap::addSpecificMapHTML()
 61+ */
 62+ public function addSpecificMapHTML( Parser $parser ) {
 63+ global $egMapsGoogleMapsPrefix, $egGoogleMapsOnThisPage;
 64+
 65+ $mapName = $egMapsGoogleMapsPrefix . '_' . $egGoogleMapsOnThisPage;
 66+
 67+ MapsGoogleMaps::addOverlayOutput( $this->output, $mapName, $this->overlays, $this->controls );
 68+
 69+ $this->output .= Html::element(
 70+ 'div',
 71+ array(
 72+ 'id' => $mapName,
 73+ 'style' => "width: $this->width; height: $this->height; background-color: #cccccc;",
 74+ ),
 75+ wfMsg( 'maps-loading-map' )
 76+ );
 77+
 78+ $parser->getOutput()->addHeadItem(
 79+ Html::inlineScript( <<<EOT
 80+addOnloadHook(
 81+ function() {
 82+ initializeGoogleMap('$mapName',
 83+ {
 84+ lat: $this->centreLat,
 85+ lon: $this->centreLon,
 86+ zoom: $this->zoom,
 87+ type: $this->type,
 88+ types: [$this->types],
 89+ controls: [$this->controls],
 90+ scrollWheelZoom: $this->autozoom
 91+ },
 92+ []);
 93+ }
 94+);
 95+EOT
 96+ ) );
 97+
 98+ }
 99+
 100+}
 101+
Index: trunk/extensions/Maps/Services/GoogleMaps/Maps_GoogleMaps.php
@@ -0,0 +1,373 @@
 2+<?php
 3+
 4+/**
 5+ * This groupe contains all Google Maps related files of the Maps extension.
 6+ *
 7+ * @defgroup MapsGoogleMaps Google Maps
 8+ * @ingroup Maps
 9+ */
 10+
 11+/**
 12+ * This file holds the general information for the Google Maps service
 13+ *
 14+ * @file Maps_GoogleMaps.php
 15+ * @ingroup MapsGoogleMaps
 16+ *
 17+ * @author Jeroen De Dauw
 18+ */
 19+
 20+if ( !defined( 'MEDIAWIKI' ) ) {
 21+ die( 'Not an entry point.' );
 22+}
 23+
 24+$wgAutoloadClasses['MapsGoogleMaps'] = dirname( __FILE__ ) . '/Maps_GoogleMaps.php';
 25+
 26+$wgHooks['MappingServiceLoad'][] = 'MapsGoogleMaps::initialize';
 27+
 28+$wgAutoloadClasses['MapsGoogleMapsDispMap'] = dirname( __FILE__ ) . '/Maps_GoogleMapsDispMap.php';
 29+$wgAutoloadClasses['MapsGoogleMapsDispPoint'] = dirname( __FILE__ ) . '/Maps_GoogleMapsDispPoint.php';
 30+
 31+$egMapsServices[MapsGoogleMaps::SERVICE_NAME] = array(
 32+ 'aliases' => array( 'googlemaps', 'google', 'googlemap', 'gmap', 'gmaps' ),
 33+ 'features' => array(
 34+ 'display_point' => 'MapsGoogleMapsDispPoint',
 35+ 'display_map' => 'MapsGoogleMapsDispMap',
 36+ )
 37+);
 38+
 39+/**
 40+ * Class for Google Maps initialization.
 41+ *
 42+ * @ingroup MapsGoogleMaps
 43+ *
 44+ * @author Jeroen De Dauw
 45+ */
 46+class MapsGoogleMaps {
 47+
 48+ const SERVICE_NAME = 'googlemaps2';
 49+
 50+ public static function initialize() {
 51+ global $wgAutoloadClasses, $egMapsServices;
 52+
 53+ self::initializeParams();
 54+
 55+ Validator::addOutputFormat( 'gmaptype', array( __CLASS__, 'setGMapType' ) );
 56+ Validator::addOutputFormat( 'gmaptypes', array( __CLASS__, 'setGMapTypes' ) );
 57+
 58+ Validator::addValidationFunction( 'is_google_overlay', array( __CLASS__, 'isGOverlay' ) );
 59+
 60+ return true;
 61+ }
 62+
 63+ private static function initializeParams() {
 64+ global $egMapsServices, $egMapsGoogleMapsType, $egMapsGoogleMapsTypes, $egMapsGoogleAutozoom, $egMapsGMapControls;
 65+
 66+ $allowedTypes = self::getTypeNames();
 67+
 68+ $egMapsServices[self::SERVICE_NAME]['parameters'] = array(
 69+ 'controls' => array(
 70+ 'type' => array( 'string', 'list' ),
 71+ 'criteria' => array(
 72+ 'in_array' => self::getControlNames()
 73+ ),
 74+ 'default' => $egMapsGMapControls,
 75+ 'output-type' => array( 'list', ',', '\'' )
 76+ ),
 77+ 'type' => array(
 78+ 'aliases' => array( 'map-type', 'map type' ),
 79+ 'criteria' => array(
 80+ 'in_array' => $allowedTypes
 81+ ),
 82+ 'default' => $egMapsGoogleMapsType, // FIXME: default value should not be used when not present in types parameter.
 83+ 'output-type' => 'gmaptype'
 84+ ),
 85+ 'types' => array(
 86+ 'type' => array( 'string', 'list' ),
 87+ 'aliases' => array( 'map-types', 'map types' ),
 88+ 'criteria' => array(
 89+ 'in_array' => $allowedTypes
 90+ ),
 91+ 'default' => $egMapsGoogleMapsTypes,
 92+ 'output-types' => array( 'gmaptypes', 'list' )
 93+ ),
 94+ 'autozoom' => array(
 95+ 'type' => 'boolean',
 96+ 'aliases' => array( 'auto zoom', 'mouse zoom', 'mousezoom' ),
 97+ 'default' => $egMapsGoogleAutozoom,
 98+ 'output-type' => 'boolstr'
 99+ ),
 100+ );
 101+
 102+ $egMapsServices[self::SERVICE_NAME]['parameters']['zoom']['criteria']['in_range'] = array( 0, 20 );
 103+ }
 104+
 105+ // http://code.google.com/apis/maps/documentation/reference.html#GMapType.G_NORMAL_MAP
 106+ private static $mapTypes = array(
 107+ 'normal' => 'G_NORMAL_MAP',
 108+ 'satellite' => 'G_SATELLITE_MAP',
 109+ 'hybrid' => 'G_HYBRID_MAP',
 110+ 'terrain' => 'G_PHYSICAL_MAP',
 111+ 'physical' => 'G_PHYSICAL_MAP',
 112+ 'earth' => 'G_SATELLITE_3D_MAP',
 113+ 'sky' => 'G_SKY_VISIBLE_MAP',
 114+ 'moon' => 'G_MOON_VISIBLE_MAP',
 115+ 'moon-elevation' => 'G_MOON_ELEVATION_MAP',
 116+ 'mars' => 'G_MARS_VISIBLE_MAP',
 117+ 'mars-elevation' => 'G_MARS_ELEVATION_MAP',
 118+ 'mars-infrared' => 'G_MARS_INFRARED_MAP'
 119+ );
 120+
 121+ private static $overlayData = array(
 122+ 'photos' => '0',
 123+ 'videos' => '1',
 124+ 'wikipedia' => '2',
 125+ 'webcams' => '3'
 126+ );
 127+
 128+ /**
 129+ * Returns the names of all supported map types.
 130+ *
 131+ * @return array
 132+ */
 133+ public static function getTypeNames() {
 134+ return array_keys( self::$mapTypes );
 135+ }
 136+
 137+ /**
 138+ * Returns the names of all supported controls.
 139+ * This data is a copy of the one used to actually translate the names
 140+ * into the controls, since this resides client side, in GoogleMapFunctions.js.
 141+ *
 142+ * @return array
 143+ */
 144+ public static function getControlNames() {
 145+ return array(
 146+ 'auto', 'large', 'small', 'large-original', 'small-original', 'zoom', 'type', 'type-menu',
 147+ 'overlays', 'overview', 'overview-map', 'scale', 'nav-label', 'nav'
 148+ );
 149+ }
 150+
 151+ /**
 152+ * Returns the names of all supported map overlays.
 153+ *
 154+ * @return array
 155+ */
 156+ public static function getOverlayNames() {
 157+ return array_keys( self::$overlayData );
 158+ }
 159+
 160+ /**
 161+ * Returns whether the provided value is a valid google overlay.
 162+ *
 163+ * @param $value
 164+ *
 165+ * @return boolean
 166+ */
 167+ public static function isGOverlay( $value ) {
 168+ $value = explode( '-', $value );
 169+ return in_array( $value[0], self::getOverlayNames() );
 170+ }
 171+
 172+ /**
 173+ * Changes the map type name into the corresponding Google Maps API v2 identifier.
 174+ *
 175+ * @param string $type
 176+ *
 177+ * @return string
 178+ */
 179+ public static function setGMapType( &$type ) {
 180+ $type = self::$mapTypes[ $type ];
 181+ }
 182+
 183+ /**
 184+ * Changes the map type names into the corresponding Google Maps API v2 identifiers.
 185+ *
 186+ * @param array $types
 187+ *
 188+ * @return array
 189+ */
 190+ public static function setGMapTypes( array &$types ) {
 191+ for ( $i = count( $types ) - 1; $i >= 0; $i-- ) {
 192+ $types[$i] = self::$mapTypes[ $types[$i] ];
 193+ }
 194+ }
 195+
 196+ /**
 197+ * Add references to the Google Maps API and required JS file to the provided output
 198+ *
 199+ * @param string $output
 200+ */
 201+ public static function addGMapDependencies( &$output ) {
 202+ global $wgJsMimeType, $wgLang;
 203+ global $egGoogleMapsKey, $egGoogleMapsOnThisPage, $egMapsStyleVersion, $egMapsJsExt, $egMapsScriptPath;
 204+
 205+ if ( empty( $egGoogleMapsOnThisPage ) ) {
 206+ $egGoogleMapsOnThisPage = 0;
 207+
 208+ MapsGoogleMaps::validateGoogleMapsKey();
 209+
 210+ $langCode = self::getMappedLanguageCode( $wgLang->getCode() );
 211+ $output .= "<script src='http://maps.google.com/maps?file=api&amp;v=2&amp;key=$egGoogleMapsKey&amp;hl={$langCode}' type='$wgJsMimeType'></script><script type='$wgJsMimeType' src='$egMapsScriptPath/Services/GoogleMaps/GoogleMapFunctions{$egMapsJsExt}?$egMapsStyleVersion'></script><script type='$wgJsMimeType'>window.unload = GUnload;</script>";
 212+ }
 213+ }
 214+
 215+ /**
 216+ * Maps language codes to Google Maps API v2 compatible values.
 217+ *
 218+ * @param string $code
 219+ *
 220+ * @return string The mapped code
 221+ */
 222+ private static function getMappedLanguageCode( $code ) {
 223+ $mappings = array(
 224+ 'en_gb' => 'en',// v2 does not support en_gb - use english :(
 225+ 'he' => 'iw', // iw is googlish for hebrew
 226+ 'fj' => 'fil', // google does not support Fijian - use Filipino as close(?) supported relative
 227+ 'or' => 'en' // v2 does not support Oriya.
 228+ );
 229+ if ( array_key_exists( $code, $mappings ) ) {
 230+ $code = $mappings[$code];
 231+ }
 232+ return $code;
 233+ }
 234+
 235+ /**
 236+ * This function ensures backward compatibility with Semantic Google Maps and other extensions
 237+ * using $wgGoogleMapsKey instead of $egGoogleMapsKey.
 238+ *
 239+ * FIXME: Possible vunerability when register globals is on.
 240+ */
 241+ public static function validateGoogleMapsKey() {
 242+ global $egGoogleMapsKey, $wgGoogleMapsKey;
 243+
 244+ if ( isset( $wgGoogleMapsKey ) ) {
 245+ if ( strlen( trim( $egGoogleMapsKey ) ) < 1 ) $egGoogleMapsKey = $wgGoogleMapsKey;
 246+ }
 247+ }
 248+
 249+ /**
 250+ * Adds the needed output for the overlays control.
 251+ *
 252+ * @param string $output
 253+ * @param string $mapName
 254+ * @param string $overlays
 255+ * @param string $controls
 256+ */
 257+ public static function addOverlayOutput( &$output, $mapName, $overlays, $controls ) {
 258+ global $egMapsGMapOverlays, $egMapsGoogleOverlLoaded, $wgJsMimeType;
 259+
 260+ // Check to see if there is an overlays control.
 261+ $hasOverlayControl = in_string( 'overlays', $controls );
 262+
 263+ $overlayNames = array_keys( self::$overlayData );
 264+
 265+ $validOverlays = array();
 266+ foreach ( $overlays as $overlay ) {
 267+ $segements = explode( '-', $overlay );
 268+ $name = $segements[0];
 269+
 270+ if ( in_array( $name, $overlayNames ) ) {
 271+ $isOn = count( $segements ) > 1 ? $segements[1] : '0';
 272+ $validOverlays[$name] = $isOn == '1';
 273+ }
 274+ }
 275+ $overlays = $validOverlays;
 276+
 277+ // If there are no overlays or there is no control to hold them, don't bother the rest.
 278+ if ( !$hasOverlayControl || count( $overlays ) < 1 ) return;
 279+
 280+ // If the overlays JS and CSS has not yet loaded, do it.
 281+ if ( empty( $egMapsGoogleOverlLoaded ) ) {
 282+ $egMapsGoogleOverlLoaded = true;
 283+ MapsGoogleMaps::addOverlayCss( $output );
 284+ }
 285+
 286+ // Add the inputs for the overlays.
 287+ $addedOverlays = array();
 288+ $overlayHtml = '';
 289+ $onloadFunctions = array();
 290+ foreach ( $overlays as $overlay => $isOn ) {
 291+ $overlay = strtolower( $overlay );
 292+
 293+ if ( in_array( $overlay, $overlayNames ) ) {
 294+ if ( ! in_array( $overlay, $addedOverlays ) ) {
 295+ $addedOverlays[] = $overlay;
 296+ $label = wfMsg( 'maps_' . $overlay );
 297+ $urlNr = self::$overlayData[$overlay];
 298+ $overlayHtml .= "<input id='$mapName-overlay-box-$overlay' name='$mapName-overlay-box' type='checkbox' onclick='switchGLayer(GMaps[\"$mapName\"], this.checked, GOverlays[$urlNr])' /> $label <br />";
 299+ if ( $isOn ) {
 300+ $onloadFunctions .= "addOnloadHook( function() { initiateGOverlay('$mapName-overlay-box-$overlay', '$mapName', $urlNr) } );";
 301+ }
 302+ }
 303+ }
 304+ }
 305+
 306+ $output .= <<<EOT
 307+<script type='$wgJsMimeType'>var timer_$mapName;</script>
 308+<div class='outer-more' id='$mapName-outer-more'><form action=''><div class='more-box' id='$mapName-more-box'>
 309+$overlayHtml
 310+</div></form></div>
 311+EOT;
 312+
 313+ if ( count($onloadFunctions) > 0 ) {
 314+ $output .= "<script type='$wgJsMimeType'>" . implode( "\n", $onloadFunctions ) . '</script>';
 315+ }
 316+ }
 317+
 318+ /**
 319+ * Add CSS for the overlays.
 320+ *
 321+ * @param $output
 322+ *
 323+ * TODO
 324+ */
 325+ private static function addOverlayCss( &$output ) {
 326+ $css = <<<END
 327+
 328+<style type="text/css">
 329+.inner-more {
 330+ text-align:center;
 331+ font-size:12px;
 332+ background-color: #fff;
 333+ color: #000;
 334+ border: 1px solid #fff;
 335+ border-right-color: #b0b0b0;
 336+ border-bottom-color: #c0c0c0;
 337+ width:7em;
 338+ cursor: pointer;
 339+}
 340+
 341+.inner-more.highlight {
 342+ font-weight: bold;
 343+ border: 1px solid #483D8B;
 344+ border-right-color: #6495ed;
 345+ border-bottom-color: #6495ed;
 346+}
 347+
 348+.more-box { position:absolute;
 349+ top:25px; left:0px;
 350+ margin-top:-1px;
 351+ font-size:12px;
 352+ padding: 6px 4px;
 353+ width:120px;
 354+ background-color: #fff;
 355+ color: #000;
 356+ border: 1px solid gray;
 357+ border-top:1px solid #e2e2e2;
 358+ display: none;
 359+ cursor:default;
 360+}
 361+
 362+.more-box.highlight {
 363+ width:119px;
 364+ border-width:2px;
 365+}
 366+</style>
 367+
 368+END;
 369+
 370+ $output .= preg_replace( '/\s+/m', ' ', $css );
 371+ }
 372+
 373+}
 374+
\ No newline at end of file
Index: trunk/extensions/Maps/Services/GoogleMaps/Maps_GoogleMapsDispPoint.php
@@ -0,0 +1,106 @@
 2+<?php
 3+
 4+/**
 5+ * File holding the MapsGoogleMapsDispPoint class.
 6+ *
 7+ * @file Maps_GoogleMapsDispPoint.php
 8+ * @ingroup MapsGoogleMaps
 9+ *
 10+ * @author Jeroen De Dauw
 11+ */
 12+
 13+if ( !defined( 'MEDIAWIKI' ) ) {
 14+ die( 'Not an entry point.' );
 15+}
 16+
 17+/**
 18+ * Class for handling the display_point(s) parser functions with Google Maps.
 19+ *
 20+ * @ingroup MapsGoogleMaps
 21+ *
 22+ * @author Jeroen De Dauw
 23+ */
 24+final class MapsGoogleMapsDispPoint extends MapsBasePointMap {
 25+
 26+ public $serviceName = MapsGoogleMaps::SERVICE_NAME;
 27+
 28+ protected $markerStringFormat = 'getGMarkerData(lat, lon, \'title\', \'label\', "icon")';
 29+
 30+ protected function getDefaultZoom() {
 31+ global $egMapsGoogleMapsZoom;
 32+ return $egMapsGoogleMapsZoom;
 33+ }
 34+
 35+ public function getSpecificParameterInfo() {
 36+ global $egMapsGMapOverlays;
 37+ // TODO: it'd be cool to have this static so it can be cheched in order to only init it once.
 38+ $this->spesificParameters = array(
 39+ 'overlays' => array(
 40+ 'type' => array( 'string', 'list' ),
 41+ 'criteria' => array(
 42+ 'is_google_overlay' => array()
 43+ ),
 44+ 'default' => $egMapsGMapOverlays,
 45+ ),
 46+ );
 47+ return $this->spesificParameters;
 48+ }
 49+
 50+ /**
 51+ * @see MapsBaseMap::doMapServiceLoad()
 52+ */
 53+ public function doMapServiceLoad() {
 54+ global $egGoogleMapsOnThisPage;
 55+
 56+ MapsGoogleMaps::addGMapDependencies( $this->output );
 57+ $egGoogleMapsOnThisPage++;
 58+
 59+ $this->elementNr = $egGoogleMapsOnThisPage;
 60+ }
 61+
 62+ /**
 63+ * @see MapsBaseMap::addSpecificMapHTML()
 64+ */
 65+ public function addSpecificMapHTML( Parser $parser ) {
 66+ global $egMapsGoogleMapsPrefix, $egGoogleMapsOnThisPage;
 67+
 68+ $mapName = $egMapsGoogleMapsPrefix . '_' . $egGoogleMapsOnThisPage;
 69+
 70+ MapsGoogleMaps::addOverlayOutput( $this->output, $mapName, $this->overlays, $this->controls );
 71+
 72+ $this->output .= Html::element(
 73+ 'div',
 74+ array(
 75+ 'id' => $mapName,
 76+ 'style' => "width: $this->width; height: $this->height; background-color: #cccccc;",
 77+ ),
 78+ wfMsg( 'maps-loading-map' )
 79+ );
 80+
 81+ $parser->getOutput()->addHeadItem(
 82+ Html::inlineScript(
 83+ <<<EOT
 84+addOnloadHook(
 85+ function() {
 86+ initializeGoogleMap('$mapName',
 87+ {
 88+ lat: $this->centreLat,
 89+ lon: $this->centreLon,
 90+ zoom: $this->zoom,
 91+ type: $this->type,
 92+ types: [$this->types],
 93+ controls: [$this->controls],
 94+ scrollWheelZoom: $this->autozoom
 95+ },
 96+ [$this->markerString]
 97+ );
 98+ }
 99+);
 100+EOT
 101+ )
 102+ );
 103+
 104+ }
 105+
 106+}
 107+
Index: trunk/extensions/Maps/Services/GoogleMaps/GoogleMapFunctions.js
@@ -0,0 +1,240 @@
 2+ /**
 3+ * Javascript functions for Google Maps functionallity in Maps.
 4+ *
 5+ * @file GoogleMapFunctions.js
 6+ * @ingroup MapsGoogleMaps
 7+ *
 8+ * @author Robert Buzink
 9+ * @author Yaron Koren
 10+ * @author Jeroen De Dauw
 11+ */
 12+
 13+var GOverlays = [
 14+ new GLayer("com.panoramio.all"),
 15+ new GLayer("com.youtube.all"),
 16+ new GLayer("org.wikipedia.en"),
 17+ new GLayer("com.google.webcams")
 18+];
 19+
 20+
 21+/**
 22+ * Returns GMarker object on the provided location. It will show a popup baloon
 23+ * with title and label when clicked, if either of these is set.
 24+ */
 25+function createGMarker(point, title, label, icon) {
 26+ var marker;
 27+
 28+ if (icon != '') {
 29+ var iconObj = new GIcon(G_DEFAULT_ICON);
 30+ iconObj.image = icon;
 31+ marker = new GMarker(point, {icon:iconObj});
 32+ } else {
 33+ marker = new GMarker(point);
 34+ }
 35+
 36+ if ((title + label).length > 0) {
 37+ var bothTxtAreSet = title.length > 0 && label.length > 0;
 38+ var popupText = bothTxtAreSet ? '<b>' + title + '</b><hr />' + label : title + label;
 39+ popupText = '<div style="overflow:auto;max-height:140px;">' + popupText + '</div>';
 40+
 41+ GEvent.addListener(marker, 'click',
 42+ function() {
 43+ marker.openInfoWindowHtml(popupText, {maxWidth:350});
 44+ }
 45+ );
 46+ }
 47+
 48+ return marker;
 49+}
 50+
 51+/**
 52+ * Returns GMap2 object with the provided properties and markers.
 53+ * This is done by setting the map centre and size, and passing the arguments to function createGoogleMap.
 54+ */
 55+function initializeGoogleMap(mapName, mapOptions, markers) {
 56+ if (GBrowserIsCompatible()) {
 57+ mapOptions.centre = (mapOptions.lat != null && mapOptions.lon != null) ? new GLatLng(mapOptions.lat, mapOptions.lon) : null;
 58+ //mapOptions.size = new GSize(mapOptions.width, mapOptions.height);
 59+ return createGoogleMap(mapName, mapOptions, markers);
 60+ }
 61+ else {
 62+ return false;
 63+ }
 64+}
 65+
 66+/**
 67+ * Returns GMap2 object with the provided properties.
 68+ */
 69+function createGoogleMap(mapName, mapOptions, markers) {
 70+ var mapElement = document.getElementById(mapName);
 71+ var typesContainType = false;
 72+
 73+ // TODO: Change labels of the moon/mars map types?
 74+ for (var i = 0; i < mapOptions.types.length; i++) {
 75+ if (mapOptions.types[i] == mapOptions.type) typesContainType = true;
 76+ }
 77+
 78+ if (! typesContainType) mapOptions.types.push(mapOptions.type);
 79+
 80+ var map = new GMap2(mapElement, {mapTypes: mapOptions.types});
 81+ map.name = mapName;
 82+
 83+ map.setMapType(mapOptions.type);
 84+
 85+ // List of GControls: http://code.google.com/apis/maps/documentation/reference.html#GControl
 86+ for (i in mapOptions.controls){
 87+ if (mapOptions.controls[i].toLowerCase() == 'auto') {
 88+ if (mapElement.offsetHeight > 75) mapOptions.controls[i] = mapElement.offsetHeight > 320 ? 'large' : 'small';
 89+ }
 90+
 91+ switch (mapOptions.controls[i]) {
 92+ case 'large' :
 93+ map.addControl(new GLargeMapControl3D());
 94+ break;
 95+ case 'small' :
 96+ map.addControl(new GSmallZoomControl3D());
 97+ break;
 98+ case 'large-original' :
 99+ map.addControl(new GLargeMapControl());
 100+ break;
 101+ case 'small-original' :
 102+ map.addControl(new GSmallMapControl());
 103+ break;
 104+ case 'zoom' :
 105+ map.addControl(new GSmallZoomControl());
 106+ break;
 107+ case 'type' :
 108+ map.addControl(new GMapTypeControl());
 109+ break;
 110+ case 'type-menu' :
 111+ map.addControl(new GMenuMapTypeControl());
 112+ break;
 113+ case 'overlays' :
 114+ map.addControl(new MoreControl());
 115+ break;
 116+ case 'overview' : case 'overview-map' :
 117+ map.addControl(new GOverviewMapControl());
 118+ break;
 119+ case 'scale' :
 120+ map.addControl(new GScaleControl());
 121+ break;
 122+ case 'nav-label' : case 'nav' :
 123+ map.addControl(new GNavLabelControl());
 124+ break;
 125+ }
 126+ }
 127+
 128+ var bounds = ((mapOptions.zoom == null || mapOptions.centre == null) && markers.length > 1) ? new GLatLngBounds() : null;
 129+
 130+ for (i in markers) {
 131+ var marker = markers[i];
 132+ map.addOverlay(createGMarker(marker.point, marker.title, marker.label, marker.icon));
 133+ if (bounds != null) bounds.extend(marker.point);
 134+ }
 135+
 136+ if (bounds != null) {
 137+ map.setCenter(bounds.getCenter(), map.getBoundsZoomLevel(bounds));
 138+ }
 139+
 140+ if (mapOptions.centre != null) map.setCenter(mapOptions.centre);
 141+ if (mapOptions.zoom != null) map.setZoom(mapOptions.zoom);
 142+
 143+ if (mapOptions.scrollWheelZoom) map.enableScrollWheelZoom();
 144+
 145+ map.enableContinuousZoom();
 146+
 147+ // Make the map variable available for other functions
 148+ if (!window.GMaps) window.GMaps = new Object;
 149+ eval("window.GMaps." + mapName + " = map;");
 150+
 151+ return map;
 152+}
 153+
 154+function getGMarkerData(lat, lon, title, label, icon) {
 155+ return {point: new GLatLng(lat, lon), title: title, label: label, icon: icon};
 156+}
 157+
 158+function setupCheckboxShiftClick() { return true; }
 159+
 160+function MoreControl() {};
 161+MoreControl.prototype = new GControl();
 162+
 163+MoreControl.prototype.initialize = function(map) {
 164+ this.map = map;
 165+
 166+ var more = document.getElementById(map.name + "-outer-more");
 167+
 168+ var buttonDiv = document.createElement("div");
 169+ buttonDiv.id = map.name + "-more-button";
 170+ buttonDiv.title = "Show/Hide Overlays";
 171+ buttonDiv.style.border = "1px solid black";
 172+ buttonDiv.style.width = "86px";
 173+
 174+ var textDiv = document.createElement("div");
 175+ textDiv.id = map.name + "-inner-more";
 176+ textDiv.setAttribute('class', 'inner-more');
 177+ textDiv.appendChild(document.createTextNode("Overlays"));
 178+
 179+ buttonDiv.appendChild(textDiv);
 180+
 181+ // Register Event handlers
 182+ more.onmouseover = showGLayerbox;
 183+ more.onmouseout = setGLayerboxClose;
 184+
 185+ // Insert the button just after outer_more div.
 186+ more.insertBefore(buttonDiv, document.getElementById(map.name + "-more-box").parentNode);
 187+
 188+ // Remove the whole div from its location and reinsert it to the map.
 189+ map.getContainer().appendChild(more);
 190+
 191+ return more;
 192+};
 193+
 194+MoreControl.prototype.getDefaultPosition = function() {
 195+ return new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(7, 35));
 196+};
 197+
 198+function checkGChecked(mapName) {
 199+ // Returns true if a checkbox is still checked otherwise false.
 200+ var boxes = document.getElementsByName(mapName + "-overlay-box");
 201+ for(var i = 0; i < boxes.length; i++) {
 202+ if(boxes[i].checked) return true;
 203+ }
 204+ return false;
 205+}
 206+
 207+function showGLayerbox() {
 208+ var mapName = this.id.split('-')[0];
 209+ eval("if(window.timer_" + mapName + ") clearTimeout(timer_" + mapName + ");");
 210+ document.getElementById(mapName + "-more-box").style.display = "block";
 211+ var button = document.getElementById(mapName + "-inner-more");
 212+ button.style.borderBottomWidth = "4px";
 213+ button.style.borderBottomColor = "white";
 214+}
 215+
 216+
 217+function setGLayerboxClose() {
 218+ var mapName = this.id.split('-')[0];
 219+ var layerbox = document.getElementById(mapName + "-more-box");
 220+ var button = document.getElementById(mapName + "-inner-more");
 221+ var bottomColor = checkGChecked(mapName) ? "#6495ed" : "#c0c0c0";
 222+ eval("timer_" + mapName + " = window.setTimeout(function() { layerbox.style.display = 'none'; button.style.borderBottomWidth = '1px'; button.style.borderBottomColor = bottomColor; }, 400);");
 223+}
 224+
 225+function switchGLayer(map, checked, layer) {
 226+ var layerbox = document.getElementById(map.name + "-more-box");
 227+ var button = document.getElementById(map.name + "-inner-more");
 228+
 229+ if(checked) {
 230+ map.addOverlay(layer);
 231+ }
 232+ else {
 233+ map.removeOverlay(layer);
 234+ }
 235+
 236+}
 237+
 238+function initiateGOverlay(elementId, mapName, urlNr) {
 239+ document.getElementById(elementId).checked = true;
 240+ switchGLayer(GMaps[mapName], true, GOverlays[urlNr]);
 241+}

Status & tagging log