Skip to content

Instantly share code, notes, and snippets.

@rclark rclark/Issues.md
Last active Jun 26, 2020

Embed
What would you like to do?
Leaflet WMS + GetFeatureInfo
<!doctype html>
<html>
<head>
<title>WMS GetFeatureInfo</title>
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.6.4/leaflet.css" />
<!--[if lte IE 8]>
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.6.4/leaflet.ie.css" />
<![endif]-->
<script src="http://cdn.leafletjs.com/leaflet-0.6.4/leaflet.js"></script>
<style type="text/css">
html, body, #map {
margin: 0px;
height: 100%;
width: 100%;
}
</style>
</head>
<body>
<div id="map"></div>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script src="L.TileLayer.BetterWMS.js"></script>
<script>
var map = L.map('map', {
center: [34,-111],
zoom: 7
});
var url = 'http://data.azgs.az.gov/arizona/wms';
L.tileLayer('http://{s}.tiles.mapbox.com/v3/rclark.map-wm3i8w1a/{z}/{x}/{y}.png').addTo(map);
L.tileLayer.betterWms(url, {
layers: 'azgs:mapunitpolys',
transparent: true,
format: 'image/png'
}).addTo(map);
</script>
</body>
</html>

There are a bunch of reasons why this is convoluted, mostly in building the URL to make the request:

  1. You have to rely on an AJAX request, this example uses jQuery
  2. To make a GetFeatureInfo request, you must provide a BBOX for a image, and the pixel coordinates for the part of the image that you want info from. A couple of squirrely lines of Leaflet code can give you that.
  3. Output formats. The info_format parameter in the request. We don't know a priori which will be supported by a WMS that we might make a request to. See Geoserver's docs for what formats are available from Geoserver. That won't be the same from WMS to WMS, however.
  4. WMS services return XML docs when there's a mistake in the request or in processing. This sends an HTTP 200, which jQuery doesn't think is an error.
L.TileLayer.BetterWMS = L.TileLayer.WMS.extend({
onAdd: function (map) {
// Triggered when the layer is added to a map.
// Register a click listener, then do all the upstream WMS things
L.TileLayer.WMS.prototype.onAdd.call(this, map);
map.on('click', this.getFeatureInfo, this);
},
onRemove: function (map) {
// Triggered when the layer is removed from a map.
// Unregister a click listener, then do all the upstream WMS things
L.TileLayer.WMS.prototype.onRemove.call(this, map);
map.off('click', this.getFeatureInfo, this);
},
getFeatureInfo: function (evt) {
// Make an AJAX request to the server and hope for the best
var url = this.getFeatureInfoUrl(evt.latlng),
showResults = L.Util.bind(this.showGetFeatureInfo, this);
$.ajax({
url: url,
success: function (data, status, xhr) {
var err = typeof data === 'string' ? null : data;
showResults(err, evt.latlng, data);
},
error: function (xhr, status, error) {
showResults(error);
}
});
},
getFeatureInfoUrl: function (latlng) {
// Construct a GetFeatureInfo request URL given a point
var point = this._map.latLngToContainerPoint(latlng, this._map.getZoom()),
size = this._map.getSize(),
params = {
request: 'GetFeatureInfo',
service: 'WMS',
srs: 'EPSG:4326',
styles: this.wmsParams.styles,
transparent: this.wmsParams.transparent,
version: this.wmsParams.version,
format: this.wmsParams.format,
bbox: this._map.getBounds().toBBoxString(),
height: size.y,
width: size.x,
layers: this.wmsParams.layers,
query_layers: this.wmsParams.layers,
info_format: 'text/html'
};
params[params.version === '1.3.0' ? 'i' : 'x'] = point.x;
params[params.version === '1.3.0' ? 'j' : 'y'] = point.y;
return this._url + L.Util.getParamString(params, this._url, true);
},
showGetFeatureInfo: function (err, latlng, content) {
if (err) { console.log(err); return; } // do nothing if there's an error
// Otherwise show the content in a popup, or something.
L.popup({ maxWidth: 800})
.setLatLng(latlng)
.setContent(content)
.openOn(this._map);
}
});
L.tileLayer.betterWms = function (url, options) {
return new L.TileLayer.BetterWMS(url, options);
};
@RadekHavelka

This comment has been minimized.

Copy link

RadekHavelka commented Apr 18, 2014

Hi, I just want to say thanks for this code, very helpful !

@tommelluish

This comment has been minimized.

Copy link

tommelluish commented Jun 13, 2014

Thanks very much for posting this example - it looks really useful! I had some problems getting it to work with my local geoserver, but firebug finally showed me that a CORS restriction was preventing geoserver returning the getFeatureInfo to my webserver. Enabling "Access data sources across domains" in Internet Explorer finally got around the problem - now I have to work out how to do that properly with CORS headers...

@Trac3rTong

This comment has been minimized.

Copy link

Trac3rTong commented Aug 7, 2014

Hi,
is it possible to get the featureinfo from more than on layer in a single pop-up window?

thanks for any help!

@lurajon

This comment has been minimized.

Copy link

lurajon commented Nov 6, 2014

Hi,

I also need the popup window to display featureinfo from more than one layer.

Thanks!

Best regards,

Jone

@hoge6b01

This comment has been minimized.

Copy link

hoge6b01 commented Mar 12, 2015

Hi, love it. Thank you very much.
One question. How and where do I define the attribute's table column that should be displayed in the popup (instead all like implemented now)? Thanks for your help. BR!

@akshara-chukkannagari

This comment has been minimized.

Copy link

akshara-chukkannagari commented Nov 18, 2015

Hi,
I love this simple and easy featureInfo in leaflet maps.
Is it possible to get the featureInfo (attributes) using an HTTP POST request instead of HTTP GET request (the URL)?
and also any way to choose the attributes to be displayed?

Thanks,
Akshara

@amarflybot

This comment has been minimized.

Copy link

amarflybot commented Dec 4, 2015

No 'Access-Control-Allow-Origin' header is present on the requested resource
I get the above error when it hit the URL: http://:7070/geoserver/MSTRUNKCAR1_MINESTAR/wms?REQUEST=GetFeatureInfo&SERVICE=WMS&SRS=EPSG%3A4326&STYLES=&TRANSPARENT=true&VERSION=1.1.1&FORMAT=image%2Fpng&BBOX=0.7881295680999756%2C0.6926046010364527%2C0.8019590377807618%2C0.6994598214130091&HEIGHT=639&WIDTH=1289&LAYERS=MSTRUNKCAR1_MINESTAR%3AMSTRUNKCAR1_ROADS&QUERY_LAYERS=MSTRUNKCAR1_MINESTAR%3AMSTRUNKCAR1_ROADS&INFO_FORMAT=text%2Fhtml&X=371&Y=326

@ezgis504

This comment has been minimized.

Copy link

ezgis504 commented Dec 6, 2015

Thanks for creating this functionality.

For me, I get a popup window, but it is blank. I am using this WMS:
http://igems.doi.gov/arcgis/services/igems_haz/MapServer/WMSServer

image

@amarflybot

This comment has been minimized.

Copy link

amarflybot commented Dec 22, 2015

@ezgis504 I think you need to map the returned function of parseResponse correctly into an object of alert. The above example is awesome.

@ezgis504

This comment has been minimized.

Copy link

ezgis504 commented Jan 3, 2016

I'm not sure how to do that. Is it something you can explain easily?

@ezgis504

This comment has been minimized.

Copy link

ezgis504 commented Jan 3, 2016

Actually, I have been playing around with it more. I can get the info window popup, but only when i click at the center of the polygon feature. Is it possible to get to work when click anywhere within the polygon?

@Tybion

This comment has been minimized.

Copy link

Tybion commented Jan 6, 2016

Thank you for unselfishly providing this code. You have saved me probably days of time.

@hoge6b01

This comment has been minimized.

Copy link

hoge6b01 commented Jan 15, 2016

Hello, I created a webmap using the BetterWMS. The app can be found at www.carstenhogertz.de/c_section . My problem is that when I click on a feature it sometimes returns a FeatureInfo sometimes not. At very large scale it even shows Infos from another Feature that I've clicked. How do I manipulate the code to the correct Features? Thanks Carsten

@Huyeng

This comment has been minimized.

Copy link

Huyeng commented Jan 16, 2016

Thanks for sharing this. I wonder that how do highlight the selected feature onclick to get info window?

@Ojaybee

This comment has been minimized.

Copy link

Ojaybee commented Apr 8, 2016

Hi I'm getting the following error when I click on a feature:

TypeError: t is undefined
...unction(t){var e=Math.PI/180,i=1-1e-15,n=Math.max(Math.min(Math.sin(t.lat*e),i),...

From leaflet.js line 5

Is this a known issue?

@hardisubagyo

This comment has been minimized.

Copy link

hardisubagyo commented Aug 23, 2016

how that feature down instead of sideways

@renelikestacos

This comment has been minimized.

Copy link

renelikestacos commented Sep 29, 2016

Thanks for sharing this pretty useful function. I wonder why Leaflet doesn't come with that.

@AngAven

This comment has been minimized.

Copy link

AngAven commented Dec 5, 2016

captura de pantalla 2016-12-05 02 20 18

It's amazing that code, thanks.
@Opadeira

This comment has been minimized.

Copy link

Opadeira commented Dec 20, 2016

Exactly what I need. Thanks for sharing.
Any Info on how you got around the CORS restriction? I get a CORS error if I click on the betterWMS layer but if I enter the resulting URL directly I get the server response correctly.

@Andrespebu

This comment has been minimized.

Copy link

Andrespebu commented Feb 9, 2017

Hola, tengo un problema que no sé resolver... Espero que alguien me ayude... Una vez inserto betterWms y ajusto los datos no aparece en mi navegador ningún popup pero la petición la hace correcta, alguna solución?
Saludos.

@fuhidev

This comment has been minimized.

Copy link

fuhidev commented Mar 24, 2017

Thanks you. Very good <3

@thanhxuan2017

This comment has been minimized.

Copy link

thanhxuan2017 commented Mar 30, 2017

Thank you @rclark.
But could you help me. I using your source code, i replace url base map and database (my wms). when i run index.html, it show image map. my mouse is hand on desktop (dont change as arrow to click a position) and dont show popup. Please, help me. Thank pro!

@thanhxuan2017

This comment has been minimized.

Copy link

thanhxuan2017 commented Apr 2, 2017

Dear AngAven,
Could you send me source code in your example. My email: mrthanhxuan@gmail.com. Thanks for help me!

@santiblanko

This comment has been minimized.

Copy link

santiblanko commented Apr 7, 2017

@thankxuan2017 in my opinion wms is old.

@marfeca94

This comment has been minimized.

Copy link

marfeca94 commented May 3, 2017

How can I display the popup only if I click on the layer and not in the basemap?

@eddiedehmous

This comment has been minimized.

Copy link

eddiedehmous commented Jun 1, 2017

I have built a nice map with layers of images from geoserver using leaflet , now i would like to add this GetfeatureInfo functionality , get the values when user click on a point , a have tested this plugin leaflet.wmsBetter but when i run it nothing happened on the map .
I rad somewhere that it could be a problem of port configuration between leaflet and geoserver .
can you help me please ?

@mitsaras

This comment has been minimized.

Copy link

mitsaras commented Jul 28, 2017

Exactly what I need. Thanks for sharing.
God bless you!

@ghost

This comment has been minimized.

Copy link

ghost commented Aug 16, 2017

amarraja123 bro use this extension.
https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi
i have the same issue like and this extension helped me out.

@maryandplus

This comment has been minimized.

Copy link

maryandplus commented Aug 27, 2017

this code is great! thanks for sharing
i had trouble with the javascript cross domain but this video: https://www.youtube.com/watch?v=o8puzjzpjqo helped
so @salman03091992 is right... if anyone wants to check if their site is working just use the browser extension.

@maryandplus

This comment has been minimized.

Copy link

maryandplus commented Sep 22, 2017

i had a problem with the pop up windows but now it's fixed.
so what you have to do if you want to upload many layers of the same type just group them in one .shp (qgis) or one directory (geoserver)

@obicd

This comment has been minimized.

Copy link

obicd commented Nov 2, 2017

Hello please help. The request appears to be working, but I am not seeing the popup with the layer attributes.

@obicd

This comment has been minimized.

Copy link

obicd commented Nov 2, 2017

below is the getinfo parameter that were posted:
N=1.1.1, X=343, Y=422, SERVICE=WMS, QUERY_LAYERS=UBDC1:SELECT_OA2, TRANSPARENT=true}
Request = GetFeatureInfo
RequestCharset = null
Version = 1.1.1
XPixel = 343
YPixel = 422

@MinChanSike

This comment has been minimized.

Copy link

MinChanSike commented Dec 6, 2017

Fix for blank popup window.

L.TileLayer.BetterWMS.js

 getFeatureInfo: function (evt) {
    // Make an AJAX request to the server and hope for the best
    var url = this.getFeatureInfoUrl(evt.latlng),
      showResults = L.Util.bind(this.showGetFeatureInfo, this);
    $.ajax({
      url: url,
      success: function (data, status, xhr) {
        var err = typeof data === 'string' ? null : data;
        //Fix for blank popup window
        var doc = (new DOMParser()).parseFromString(data, "text/html"); 
        if (doc.body.innerHTML.trim().length > 0)
          showResults(err, evt.latlng, data);
      },
      error: function (xhr, status, error) {
        showResults(error);
      }
    });
  },
@cgalvist

This comment has been minimized.

Copy link

cgalvist commented Feb 7, 2018

This code is great. Thank you.

@ArchTopo

This comment has been minimized.

Copy link

ArchTopo commented Feb 26, 2018

It Works verk well, but i Would be grateful IF you could help me With this. My getfeatureinfo is a table of a raster with Only one value. How to parse this value to variable?
Thanks in advance

@markgis

This comment has been minimized.

Copy link

markgis commented Mar 20, 2018

This was really handy, thanks.

For 1.3.0 getfeatureinfo the lat and longs have been reversed so the bbox: this._map.getBounds().toBBoxString(), line doenst work. A quick function to create a string with the lat and longs in the right order solved it.

@dior1

This comment has been minimized.

Copy link

dior1 commented May 17, 2018

Is there a way to enlarge the klick area from who the info get? And if I get the info from 2 or more layers how do I show this in a popup with tabs?

@anakaine

This comment has been minimized.

Copy link

anakaine commented Oct 14, 2018

Hey Ryan, is seems like you 1st August blocks example of this is broken. Ive been trying to implement your solution but not been having much luck unfortunately. Not seeing a popup at all on leaflet 1.3.4

Also, @santiblanko wms may have been around for some time, but that neither makes it old or the implied 'not as useful. There are plenty of situations where it is still the best and fastest option, particularly with raster data.

http://bl.ocks.org/rclark/6908938

@ISURU9900

This comment has been minimized.

Copy link

ISURU9900 commented Oct 25, 2018

I was able successfully run this BetterWMSLayer. But now I want to show the attributes of a raster through a marker popup. Any idea?

@ATejed

This comment has been minimized.

Copy link

ATejed commented Dec 17, 2018

Is there a way to enlarge the klick area from who the info get?

I have the same problem. How did you solve it? @dior1

@Tim0917

This comment has been minimized.

Copy link

Tim0917 commented Jan 11, 2019

Super awesome!

Question:
How do i select a single value of the wms?
So, i want just one popup, for one value.
Somewhere there is a selection needed, but how??

Please help :)

@ivominic

This comment has been minimized.

Copy link

ivominic commented Feb 22, 2019

Is there a way to enlarge the klick area from who the info get?

I have the same problem. How did you solve it? @dior1

If you want to get info for multiple features, you should add
feature_count: '5',
to parameter list in getFeatureInfoUrl, and set number of maximum features you want to show info.

capture

@aichaous

This comment has been minimized.

Copy link

aichaous commented Mar 24, 2019

it worked but i have a blank popup

@nmtoken

This comment has been minimized.

Copy link

nmtoken commented Aug 12, 2019

     params = {
      request: 'GetFeatureInfo',
      service: 'WMS',
      srs: 'EPSG:4326',
      styles: this.wmsParams.styles,
      transparent: this.wmsParams.transparent,
      version: this.wmsParams.version,      
      format: this.wmsParams.format,
      bbox: this._map.getBounds().toBBoxString(),
      height: size.y,
      width: size.x,
      layers: this.wmsParams.layers,
      query_layers: this.wmsParams.layers,
      info_format: 'text/html'
    };

params[params.version === '1.3.0' ? 'i' : 'x'] = point.x;
params[params.version === '1.3.0' ? 'j' : 'y'] = point.y;

You have switch of x/y for i/j dependent on version, but version also switches other things, for example the parameter for specifying the Coordinate Reference system is CRS not SRS in WMS 1.3.0.

Also in WMS 1.3.0 the axes order as specified by EPSG is honoured, so EPSG:4326 is specified with a lat/long bounding box and not as per WMS 1.1.1 in long/lat order.

@madmierul

This comment has been minimized.

Copy link

madmierul commented Sep 23, 2019

hai admin.this code working well on desktop.but when open it mobile the information of the layer clicked not popup.
is there any method to fix this issue.Hope reply this comment very soon.

@Virgil-z

This comment has been minimized.

Copy link

Virgil-z commented Nov 5, 2019

hello, thanks for the amazing extension.
i have one question though.. im relatively new to WMS and GIS in general.
im using leaflet at the moment along with your extension and it works great ! however i dont seem to be able to like "select" an state ( as in highlight borders of it ) when its clicked. i have searched for days and i have yet to come up with a solution...

am i doing something wrong?can i not use the coordinates that GetFeatureInfo returns? or is there some sort of automated highlighting border function etc that im not aware of?

@madmierul

This comment has been minimized.

Copy link

madmierul commented Nov 5, 2019

try using cql_filter

@Virgil-z

This comment has been minimized.

Copy link

Virgil-z commented Nov 10, 2019

try using cql_filter

that seems to be very helpful! thanks!
however, if i use this approach, i would have to then add a new image layer for every highlight that i want to make and my styling is limited to styles which is defined ( to my understanding ) as server side.

what i want to do is like highlight the area around a state for example using polygon or some other object...
its weird because i see coordinates that GetFeatureInfo returns but i cant seem to add a polygon using those coordinates..
i tried adding polygons using leaflet and the coordinates in GetFeatureInfo but nothing shows up on the map.
did i get something wrong?is that not something i can do? like click a state on the map and highlight it using a polygon ?

@madmierul

This comment has been minimized.

Copy link

madmierul commented Nov 12, 2019

@Abhishek950650

This comment has been minimized.

Copy link

Abhishek950650 commented Nov 30, 2019

sir thanks for this code i solve my problem exactly

@jlsevillano

This comment has been minimized.

Copy link

jlsevillano commented Dec 13, 2019

Hi,
I'm using this library. Everything looks works right:
1.- I load a WMS from geoserver, ok
2.- From html form I do a filter
3.- I setParameters (filter paramaters)
4.- The WMS apply the cql_filter
5.- Display the items filtered
6.- I can do getFeatureInfo and recive the data
¡¡But if I click on the map over a hidden item or should not be there (an item) I GET THE featureInfo!! And I should not get anything.
Am i doing something wrong?

myLayer.setParams({cql_filter :final_geo_query},false); myLayer.redraw();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.