Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ability to add custom maptypes with the googlemaps service #23

Open
JeroenDeDauw opened this issue Mar 28, 2014 · 7 comments
Open

Ability to add custom maptypes with the googlemaps service #23

JeroenDeDauw opened this issue Mar 28, 2014 · 7 comments

Comments

@JeroenDeDauw
Copy link
Member

Import from https://bugzilla.wikimedia.org/show_bug.cgi?id=44869

It would be great to be able to add custom map types to the googlemaps service. In my specific case, for instance, I would like to overlay the map offered by the Norwegian Mapping Authority (Statens Kartverk) alongside Google's terrain map. Documentation for how to do this can be found here: https://developers.google.com/maps/documentation/javascript/maptypes#CustomMapTypes

Using a practical example, with the Norwegian Mapping authority as described, the Javascript code would/could like like this:

function StatkartMapType(name, layer) {
  this.layer = layer
  this.name = name
  this.alt = name
  this.tileSize = new google.maps.Size(256,256);
  this.maxZoom = 19;
  this.getTile = function(coord, zoom, ownerDocument) {
    var div = ownerDocument.createElement('DIV');
    div.style.width = this.tileSize.width + 'px';
    div.style.height = this.tileSize.height + 'px';
    div.style.backgroundImage = "url(http://opencache.statkart.no/gatekeeper/gk/gk.open_gmaps?layers=" + this.layer + "&zoom=" + zoom + "&x=" + coord.x + "&y=" + coord.y + ")";
    return div;
  };
}

var map;

function initialize() {
  var mapOptions = {
    zoom: 8,
    center: new google.maps.LatLng(60,9),
    mapTypeControlOptions: {
      mapTypeIds: ['topo2', google.maps.MapTypeId.TERRAIN]
    }
  };
  map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
  map.mapTypes.set('topo2',new StatkartMapType("S.Kartverk", "topo2"));
  map.setMapTypeId('topo2');
}

-- kvolden@gmail.com 2013-02-11 11:34:08 UTC

@kvolden
Copy link
Contributor

kvolden commented Mar 23, 2015

I'm the one who originally posted this enhancement request, and I finally got around to fork and try to implement this. I have a working version, where an associative array is provided in the options file consisting of the type name as key and the javascript function as value. In all cases the user passes only the type name as parameter in the parser function/tag, but I'm a bit unsure as to which of the following options is the best approach:

  1. Passing the javascript function as a string to the JSON-object that the jquery-code picks up along with the rest of its options-object. This function is simply evaluated with "new " and attached to the maptype registry.
  2. Passing a set of values (name, maxzoom, tilesize, url, zoom parameter name, y parameter name etc.) that will be used to construct the function/object in the jquery code that will be attached to the maptype registry. This avoids passing actual javascript code, but is less clean in other ways.
  3. Injecting the javascript functions from the options file in a script-tag in the html so that they are directly reachable from the jquery code without first being passed as strings in a JSON-object and then evaluated.

The solution I have now uses option 1. I kind of like option 3, but I'm not sure if this breaks any mediawiki or Maps-extension coding styles/best practices. I'm also not completely sure where, code wise, it would be appropriate to do such an injection.

@JeroenDeDauw
Copy link
Member Author

Hey @kvolden, thanks for looking into this.

I'm very dubious about putting JavaScript function definitions, or indeed, any executable JavaScript code, into PHP variables or JSON. Programatically constructing code in general is suspect.

@kvolden
Copy link
Contributor

kvolden commented Mar 25, 2015

Yes, I agree it's not very pretty. I figured since it's all client side, and only admins with access to Local_settings.php would be able to insert the function, there's no real security risk. There isn't really any significant difference from how OpenLayers are handled (see e.g. line 255 in Maps_settings.php where JS is put in a PHP variable as a string, which has "new " added to it in e.g. line 201 in Maps_DisplayMapRenderer.php, only to be passed to eval() in line 279 in jquery.openlayers.js). But as a matter of principle, I admit it's not very clean.

Anyway, to implement option 2 is perfectly doable. And probably preferable, the more I think about it. I guess that would amount to defining the custom maps in Local_settings.php as an associative array with typename as key and another (probably associative) array as value. There would need to be two values that would be absolutely required (name and url), while the rest would be either optional in the JS or could be defaulted to sensible values. In fact, the original example in the first post could be defined thus in Local_settings.php:

$GLOBALS[egMapsGMaps3CustomMapTypes] = array (
    'nma' => array ('name' => 'Norway Topographic', 'url' => 'http://opencache.statkart.no/gatekeeper/gk/gk.open_gmaps?layers=topo2')
);

Additional values would have to be passed if the parameters of the service does not match the names of the parameters googlemaps uses ("zoom", "x", "y"), or if it's a different tile size, and so on.

@JeroenDeDauw
Copy link
Member Author

That sounds good

@JeroenDeDauw
Copy link
Member Author

@kvolden still want to have this added to the Maps extension?

@kvolden
Copy link
Contributor

kvolden commented Jul 5, 2018

@JeroenDeDauw Sorry, the project where I needed this stalled, but I'm planning on picking it back up when I get time. And yes, the ability to use custom map overlays like described would be very nice (in fact, it is a must-have for that particular project). Are you thinking about implementing it? I don't remember how far I got in my attempt, but I'll see if I can find it when I have some time.

@JeroenDeDauw
Copy link
Member Author

Oh... I thought you had working code already.

Not planning on implementing this myself but will be happy to review a pull request that adds it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants