Leaflet geosearching / geocoding plugin

8,609 views
Skip to first unread message

Stephan Meijer

unread,
Dec 23, 2012, 8:34:19 PM12/23/12
to leafl...@googlegroups.com
Hi all,

I needed some geosearching functionality in Leaflet. So I thought: "Why not create an plugin for that".

And off-course, share it with all of you :) As there is only one place to share:


The demo uses an Google API, but the control can use an Esri or OpenStreetMap also. If you need to use your own geocoding service, just write an provider. It really isn't that hard. See the included OpenStreetMap provider for example.

Merry Christmas! :)

Arnie Shore

unread,
Dec 23, 2012, 8:45:02 PM12/23/12
to leafl...@googlegroups.com
Stephan, so nice! Thank you very very much.
> provider<https://github.com/smeijer/L.GeoSearch/blob/master/src/js/l.geosearch.provider.openstreetmap.js>for
> example.
>
> Merry Christmas! :)
>
> --
>
>
>
>

Paulo Vieira

unread,
Dec 23, 2012, 9:47:57 PM12/23/12
to leafl...@googlegroups.com
It works really nice, thanks Stephan!

If the name to be searched is very common, it fails (I got results in Brazil, but I was searching for places in Portugal). But it's simply a matter of appending the country to the search string (or even the city). So if the map application is localized to a region, a simple customization in the code will make it work better.

Have a nice christmas all!


--
 
 
 

Stephan Meijer

unread,
Dec 23, 2012, 10:07:38 PM12/23/12
to leafl...@googlegroups.com

You could use the Esri provider,and pass in the country as option.

Just like:

new L.Control.GeoSearch({
    provider: new L.GeoSearch.Provider.Esri({country: 'Portugal'})
}).addTo(map);

Thats possible with the OpenStreetMap provider also, but there you need to provide a 'countryCode'. I guess Portugal has code 'PT'?

And I'm not quite sure, but I think that thats where the google sensor parameter is for. I'll look at that for you tomorrow.

If that's the case, then this should work:

new L.Control.GeoSearch({
    provider: new L.GeoSearch.Provider.Google({sensor: true})
}).addTo(map);

Again, not sure about the last one. Esri and OSM should devenitely work.

Op 24 dec. 2012 03:48 schreef "Paulo Vieira" <paulo...@gmail.com> het volgende:
--
 
 
 

Stephan Meijer

unread,
Dec 24, 2012, 8:10:00 AM12/24/12
to leafl...@googlegroups.com
I read the Google API docs again, and was wrong about the sensor parameter indeed. But, good news! There is an "region" parameter, so I've added that to the Google provider.

Google uses the ccTLD ("top level domain") for region specification/identification, that's "pt" for Portugal.

Usage like:

        new L.Control.GeoSearch({
            provider: new L.GeoSearch.Provider.Google({
            	region: 'pt'
            })
        }).addTo(map);


For an demo, search for 'Rua do sol' on the demo page, with and without the region parameter:
 

Thanks for noticing this behavior :)

I'll update the docs later on.


Op maandag 24 december 2012 03:47:57 UTC+1 schreef Paulo Vieira het volgende:

Paulo Vieira

unread,
Dec 26, 2012, 9:26:47 PM12/26/12
to leafl...@googlegroups.com
Thanks for the improvement in the google geocoding interface!

Here are some more suggestions to make it even better (at least for the google geocoding service):

1) Since there some more optional parameters in the google API,  why not use them? "bounds", "language", "components",..., these could be handy for some situations and make the plugin more precise.

2) Add a "suffix" option (or something similar), a simple string that would be appended to the request. It could be useful if the user wants to restrict the search to some region, such as a city or a region. I believe the "region" option in the google API accepts only top-level domains (such as ".pt"), which is clearly insufficient. 

Example: say I wanted to search for "Av. Elias Garcia", in Lisbon  For some reason, a lot of places have a street with that name. If I search using only the new "region" option ("region: 'PT'"), I get the wrong the result. If I append ", Lisbon, Portugal" (or simply ", Lisbon"), I get the correct result. So it's a bit hacky and probably depends the service provider, but in the end the chance of getting the correct result is greater.

3) Finally, it would be great to have a list of the partial results in real time, as the user writes the place (like in googlemaps) - how hard is this? :-)

Thanks again.




--
 
 
 

Jason Sanford

unread,
Dec 27, 2012, 12:46:08 AM12/27/12
to leafl...@googlegroups.com
I hate to be that guy, but you probably want to look at the Google Maps Terms of Service (https://developers.google.com/maps/terms) before investing too much time in the Google geocoder.

Item 10.1.1(g) explicitly forbids doing this type of thing.

    "For example, you must not use geocodes obtained through the Service in conjunction with a non-Google map."



--
 
 
 

Michael Savarese

unread,
Dec 27, 2012, 11:47:06 PM12/27/12
to leafl...@googlegroups.com
Jason, I had high hopes that Google eased up on usage till I got to you're comment. oh well, I'll just keep using Bing geocoder. although I wish Bing supplied a point to put a marker.

Stephan Meijer

unread,
Dec 28, 2012, 11:32:48 AM12/28/12
to leafl...@googlegroups.com
I've updated the provides to give it a more clean, leaflet way of (programming) look. They are backwards compatible, I've just wrote them differently as in syntax.

1) Optional parameters

The providers now provide support for "unknown" parameters. You'll just have to put them in the options, and the provider will convert them to url parameters, without knowing what you're actually feeding it with. So they're not only supporting the parameters Google has at this moment, like "bounds", "language" and "components", but they will automatically support every parameter Google (and OSM/Esri) will introduce in the (near) future.

Just pass them in like:

   new L.Control.GeoSearch({
       provider: new L.GeoSearch.Provider.Google({
          language: 'en',
          region: 'nl'
       })
   }).addTo(map);

It works the same way for the OpenStreetMap and Esri providers.

2) Suffix Option

I'm not sure, what if you append 'Lisbon', and the user is searching for 'Av. Elias Garcia, Lisbon'. That will result in a query like: 'Av. Elias Garcia, Lisbon, Lisbon' if you implement it in a simple way, and just append the 'suffix'. As you can imagine there will be no results at all, instead of better results. I guess this is where the "bounds" parameter comes in. The bounds parameter gets a viewport, and prioritize results within that area above the results outside of you're viewport. Let me know if this works for you.

3) Real-time results

It can be done. I'll take a look at it. But remember, real-time results will increase the requests you're site's making to Google exponentially. There is a limit for 2,500 requests a day (100,000 for business accounts). A simple query will become like 10 requests in no-time. So it's not useful if you're having a very busy site. Let me correct that, it is useful, but you're running against Google's limits very fast.


Some handy links
Couple of links to find the supported parameters (I still need to update the docs at github)





Op donderdag 27 december 2012 03:26:47 UTC+1 schreef Paulo Vieira het volgende:

Stephan Meijer

unread,
Dec 28, 2012, 11:35:50 AM12/28/12
to leafl...@googlegroups.com
Do you know if using a Google basemap (and thus showing the Google copyright) equals "using a Google map"? If that's the case, then we can easily work around it.


Op donderdag 27 december 2012 06:46:08 UTC+1 schreef Jason het volgende:

Stephan Meijer

unread,
Dec 28, 2012, 12:35:49 PM12/28/12
to leafl...@googlegroups.com
Added a bing geocoder provider. Use it like:

        new L.Control.GeoSearch({
            provider: new L.GeoSearch.Provider.Bing({
                key: '__YOUR_BING_API_KEY_HERE__'
            })
        }).addTo(map);
 
Remember to request your (free) bing api key at http://bingmapsportal.com



Op vrijdag 28 december 2012 05:47:06 UTC+1 schreef Michael Savarese het volgende:

Ariel Faur

unread,
Jan 3, 2013, 3:25:00 PM1/3/13
to leafl...@googlegroups.com
Hi Stephan,

Great job! I have tried Bing and Google geocoder providers and they work pretty well. I have one question though. I've been reading through Google Maps API documentation and the  GeocoderResults object seems to return a lot more data . I understand it would be hard work to develop a common interface that supports all features of each provider. I just wonder whether we would eventually need this data in the future, particularly those properties within the geometry object.

Geocoding Results

results[]: {
 types
[]: string,
 formatted_address
: string,
 address_components
[]: {
   short_name
: string,
   long_name
: string,
   types
[]: string
 
},
 geometry
: {
   location
: LatLng,
   location_type
: GeocoderLocationType
   viewport
: LatLngBounds,
   bounds
: LatLngBounds
 
}
}

Stephan Meijer

unread,
Jan 3, 2013, 6:20:07 PM1/3/13
to leafl...@googlegroups.com
The providers collect the point.X, point.Y (lat/lon) and the formatted address currently. They place the collected data in an array to support realtime response/suggestions or an list with "best matches" in the future.

I guess we can use the "bounds" also, to determine the best zoom level. The zoom level is currently set to an configurable fixed level, collecting result bounds should make it possible to "zoom to bounds", for an best fit (street level, city level, country level, etc).

I can't come up with an reason to include the other data that the providers deliver. If you can come up with some idea's that use the remaining data, let me know. I don't think we should include data that doesn't have any purpose (in the (near) future).

Op donderdag 3 januari 2013 21:25:00 UTC+1 schreef Ariel Faur het volgende:

Leaflet Newbie

unread,
Jan 5, 2013, 8:09:48 PM1/5/13
to leafl...@googlegroups.com
Hello,

Thank you for this pluggin that match with severag map providers.

Do you think autocompletion could be added easily ?

Regards,
Florent

MB HH

unread,
Jan 7, 2013, 3:18:42 PM1/7/13
to leafl...@googlegroups.com
Very nice and useful feature!
If i want to have a little search icon before the search label, where i have to insert it?

Martin Friedrich

unread,
Jan 13, 2013, 12:57:31 PM1/13/13
to leafl...@googlegroups.com
Great work. Works very good. On Android Devices there is a Problem whith characters like 'ä', 'ö', 'ß' when using the stock browser. Using Firefox on Android works fine. Do you think it's something could be changed in the script?

Many thanks for the great work so far.

Regards

Martin

Ariel Faur

unread,
Jan 17, 2013, 12:33:40 PM1/17/13
to leafl...@googlegroups.com
Hi again Stefan,

I am working with your plugin already and I have a question regarding IE9. For some reason the async $.getJSON call within L.Control.GeoSearch seems to fail when runningo n IE9. I read there are issues with callbacks in IE but I am not sure whether it is related.

So within L.Control.GeoSearch, while testing on IE, I realized the callback function passed to $.getJSON is never executed and therefore ParseJSON and this._showLocation  are never inkoked.  Any ideas on how to solve this issue on IE ? This works well on Chrome and FF.


geosearch: function (qry) {
        try {
            var provider = this._config.provider;
            var url = provider.GetServiceUrl(qry);
            $.getJSON(url, function (data) {
                try {
                    var results = provider.ParseJSON(data);
                    if (results.length == 0)
                        throw this._config.notFoundMessage;
                    this._showLocation(results[0].X, results[0].Y, results[0].Label);
                                                          
                }
              catch (error) {
 
              }
            }.bind(this));
        }
        catch (error) {
          
        }
    }

Stephan Meijer

unread,
Jan 17, 2013, 3:07:45 PM1/17/13
to leafl...@googlegroups.com
$('#leaflet-control-geosearch-qry').parent().append('<span>boooooooo</span>');
@Leaflet Newbie
Autocompletion / suggestion can be added, but I need some time for that.


@MB HH,
To place the icon inside the search input, you could simply use an background-image trough css.

To place the icon before the input, you have to use a custom line of javascript. There is currently no option build in for that. Please use the next line of javascript to place your icon. Replace "prepend" with "append" to place the icon after the search input.
$('#leaflet-control-geosearch-qry').parent().prepend('<img src="./search-icon.png" />');

@
Martin Friedrich
I need to take a look at that later. I'm not sure if that's in control of the website / script builders, of if that's something of the browser builders. It has to do something with character encoding, but I'm not sure where precisely.

Do you experience this behavior with all of the providers?



@Ariel Faur
I've fixed the IE compatibility. Had to do with not receiving jsonp compliant code from Googles side. Could you please try the latest version from github?
Thanks for all of your comments! Great to see the plugin being used and appreciated.

Ariel Faur

unread,
Jan 18, 2013, 6:22:18 PM1/18/13
to leafl...@googlegroups.com
Hi Stefan

unfortunately the latest version from github with the jQuery.support.cors parameter didn't work for me on IE9. However, I solved the issue by making some changes to the class based on some research I did on stackoverflow. So, it works now on IE9 (but not on IE8 and under) .I basically detect whether the browser is IE and use the XDomainRequest class to enable cross domain requests on IE. Maybe the code can be improved, but this is a sample of  what it looks like right now (full code attached).



 geosearch: function (qry) {

      var provider = this._config.provider;
      var url = provider.GetServiceUrl(qry);
      if (!($.browser.msie && window.XDomainRequest)) {
        try {
          $.getJSON(url, function (data) {
            try {
              this._handleSuccess(data);
            }
            catch (error) {
              this._printError(error);
            }
          }.bind(this));
        }
        catch (error) {
          this._printError(error);
        }
      } else {
        // Use Microsoft XDR
        var xdr = new XDomainRequest();
        xdr.open("get", url);
        xdr.onload = function () {
          try {
            var data = jQuery.parseJSON(xdr.responseText); // we must parse response from XDR object
            this._handleSuccess(data);
          } catch (error) {
            this._printError(error);
          }
        }.bind(this);
        xdr.onerror = function () {
          this._printError(xdr.responseText);
        }.bind(this);
        xdr.send();
      }
    },
    
    _handleSuccess: function (data) {
      var results = this._config.provider.ParseJSON(data);

      if (results.length == 0)
        throw this._config.notFoundMessage;
      this._showLocation(results[0].X, results[0].Y, results[0].Label);
    },
l.control.geosearch.js

Stephan Meijer

unread,
Jan 18, 2013, 9:00:11 PM1/18/13
to leafl...@googlegroups.com
The problem is that Google decided to drop jsonp support when they introduced v3 of their Google Maps API. The second version of the API supported it, but they dropped it at the third version.

I'm not sure if we need to start hacking around to support something that Google broke deliberately.

I've updated the code to support Google in an other way, but I'm not entirely happy about it. Instead of just talking to an restfull backend, we now have to load the entire Google Maps api (javascript file). So this means more data, even if your user doesn't use the search.

I would advise you to use the Bing, Esri or Openlayers provider whenever possible.

Could you check the latest version on github? The last time I only tested locally, I didn't realize that CORS has an different behavior on localhost compared to running online at an domain like on github.

Thanks,
Stephan


Op zaterdag 19 januari 2013 00:22:18 UTC+1 schreef Ariel Faur het volgende:

Stephan Meijer

unread,
Jan 18, 2013, 9:06:35 PM1/18/13
to leafl...@googlegroups.com
Sorry, forget to mention. I've changed both the control and the Google provider. So you might want to update the files "l.control.geosearch.js" and "l.geosearch.provider.google.js". All other files where left unchanged. The control as well as the provider are completely backwards compatible. You shouldn't need to change your html files / initialization code, and all other providers are working as they did before.


Op zaterdag 19 januari 2013 03:00:11 UTC+1 schreef Stephan Meijer het volgende:

Ariel Faur

unread,
Jan 18, 2013, 11:43:42 PM1/18/13
to leafl...@googlegroups.com
Great, I will check it out. One more question. You suggested using Bing, Esri or Openlayers providers whenever possible. But the problem with that is I would need to switch to their maps too. According the terms I am only allowed to use a geocoding service with the same map provider. I've tried OSM geocoding (nominatim) but it is very limited and does not find all addresses.

I've briefly tested Nokia Maps API which looks quite promising. Their use terms also seem more "relaxed".

--
 
 
 

scottydavo

unread,
Jan 19, 2013, 6:05:09 PM1/19/13
to leafl...@googlegroups.com
Hi Stephan, great plugin!

I've been testing the plugin on a WebKit browser (BlackBerry PlayBook) and have come across an issue whereby the 'enter' key is not being detected and therefore the search query is not being submitted. It works fine in Chrome & IE9.
 
Just wondering if you (or anyone else here) has come across this issue, or have any suggestions?
Thanks!

Scott

Stephan Meijer

unread,
Jan 20, 2013, 10:48:18 AM1/20/13
to leafl...@googlegroups.com
Actually, that is a condition that Google set. You may only use the Google provider in conjunction with a Google Map. I even don't know if it's enough to use a Google basemap in the Leaflet viewer to met the condition.

I can't find anything about that on the Bing therms of usage. I can only find that you're limited to 10,000 requests a month, while Google limits you to 2,500 a day.

I'm not familiar with the Nokia therms, but i've added a Nokia provider for you. 


Op zaterdag 19 januari 2013 05:43:42 UTC+1 schreef Ariel Faur het volgende:

Stephan Meijer

unread,
Jan 20, 2013, 10:50:12 AM1/20/13
to leafl...@googlegroups.com
I can't test it on a playbook, since i don't own such a device. Do you know if there is any way to test the bug on a Windows computer? Is there an emulator or webkit based browser that has the same problem?

Op zondag 20 januari 2013 00:05:09 UTC+1 schreef scottydavo het volgende:

Michael Savarese

unread,
Jan 27, 2013, 12:05:14 PM1/27/13
to leafl...@googlegroups.com
Sorry, but I have a JavaScript Newb question. First of all, very nice plugin. I wish I had the skills to contribute to a plugin. 

So the question is, how and where can I implement a listener that the user has entered an address and hit enter so I can initiate some layer creation. The point(latlong) is my cql_filter on a call to GeoServer. 
I've made the xy data needed available with: window.thisAddress = results;

I just need a way to get my .ajax() call started. Any suggestions would be greatly appreciated. 

I apologize in advance if this is the wrong venue for a question like this, 

Michael

Stephan Meijer

unread,
Jan 27, 2013, 2:10:16 PM1/27/13
to leafl...@googlegroups.com
Hi Michael,

Thanks for your question :) This vanue is fine by me.

I've added two events for you, see the updated code on github.

The first event that gets fired is 'geosearch_foundlocations'. This event fires as soon as the locations are returned from the end service, and the response is parsed. It returns a list with all found locations, with the properties X, Y and Label.
map.on('geosearch_foundlocations', function(results) {
   for(var i = 0; i < results.Locations.length; i++)
      console.log(results.Locations[i].Label);
});
The second event is called as soon as the map starts to move to the found location. It returns the the same data as the 'foundlocations' event, but this time only a single record is returned instead of an array.
map.on('geosearch_showlocation', function(result) {
   console.log('zoom to: '+result.Location.Label);
});
You can hook your call in like:

map.on('geosearch_showlocation', function(result) {
   $.ajax({
      type: 'POST',
      url: 'http://yourdomain.com/endpoint',
      data: { x: result.Location.X, y: result.Location.Y }
   }).done(function(response) {
      //data submitted
   });
});

Hope this helps you out.



Op zondag 27 januari 2013 18:05:14 UTC+1 schreef Michael Savarese het volgende:

Michael Savarese

unread,
Jan 27, 2013, 5:58:11 PM1/27/13
to leafl...@googlegroups.com
Stephan, thanks so much for the quick reply and detailed solutions.  Everything worked out great.
At some point I need to learn more about ajax calls and available options.

Is there a more efficient way to build the url request to GeoServer? The way I did it seems so crude. I've heard of OpenLayers having a default_params and mergeParams option but I never did use them. 
Is there a javascript or even jquery way to build the url needed.

here's a snippet of what I use. It's ugly but it works. I'm sure at some point an extended class will be necessary for me. But thats a bit over my head for right now.

Any suggestions of where I should research would be great

function handleJson(data) {
map.removeLayer(geojsonLayer);
//geojsonLayer = new L.GeoJSON();
geojsonLayer.addData(data);
geojsonLayer.setStyle(defaultStyle);
geojsonLayer.addTo(map);
}

map.on('geosearch_showlocation', function(result) {

thisBbox = '&bbox=' + map.getBounds().toBBoxString();
maxFeatures = "&maxFeatures=100"
theRest = "&outputFormat=json&format_options=callback:getJson"
thisFilter = "&cql_filter=CONTAINS(the_geom, POINT(" + thisLatLon + "))"
thisUrl = rootUrl + thisFilter + theRest

$.ajax({
url : thisUrl,
dataType : 'jsonp',
jsonpCallback : 'getJson',
success : handleJson,
});
}); 

again, thanks for the help.

Michael


--
 
 
 

Stephan Meijer

unread,
Jan 27, 2013, 6:22:46 PM1/27/13
to leafl...@googlegroups.com
A bit of code to help you get on the right track. Hope it helps.

(customParameters overrule defaultParameters)
var rootUrl = 'http://geoserver.capecodgis.com/geoserver/capecodgis/ows'

var defaultParameters = {
    service: 'WFS',
    version: '1.0.0',
    request: 'GetFeature',
    typeName: 'capecodgis:blockgroups_2010_4326',
    maxFeatures: 100,
    outputFormat: 'json',
    format_options: 'callback:getJson'
};

var customParams = {
    bbox: map.getBounds().toBBoxString(),
    cql_filter: 'CONTAINS(the_geom, POINT('+thisLatLon+'))'
};

var parameters = L.Util.extend(defaultParameters, customParams);
        
console.log(rootUrl + L.Util.getParamString(parameters));

Op zondag 27 januari 2013 23:58:11 UTC+1 schreef Michael Savarese het volgende:

Michael Savarese

unread,
Jan 27, 2013, 8:08:21 PM1/27/13
to leafl...@googlegroups.com
Sorry to bother you but even though the url looks fine it returns the following error:

<?xml version="1.0" ?>
<ServiceExceptionReport
   version="1.2.0"
   xmlns="http://www.opengis.net/ogc"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.opengis.net/ogc http://schemas.opengis.net/wfs/1.0.0/OGC-exception.xsd">
   <ServiceException>
      bbox and cql_filter both specified but are mutually exclusive
</ServiceException></ServiceExceptionReport>

does it have something to do with different xml versions as above?

btw, thanks for setting up my url code with some L.Util magic, things are starting to make sense to me.

Michael
> --
>  
>  
>  

Michael Savarese

unread,
Jan 27, 2013, 9:46:20 PM1/27/13
to leafl...@googlegroups.com
I did some research and it's apparently an ogc standards requirement. It says the bbox must be embedded within the filter call. Have no idea how to do that but don't need that capability at the moment. I just commented out the bbox.

Again, thanks for your help, I got quite a bit done with my new found knowledge.

Martin Friedrich

unread,
Feb 7, 2013, 2:49:43 PM2/7/13
to leafl...@googlegroups.com
Hi Stefan,

I now tested it with other providers. It is the same. But only on the Android device with the Android Stock Browser. Example: You search for "Köln" has no result. Searching for "Koeln" will find the German City Cologne.

Regards,
Martin

Bill Morris

unread,
Apr 29, 2013, 4:37:15 PM4/29/13
to leafl...@googlegroups.com
Stephan,

Thanks for the great utility. I'm finding that it works perfectly on the functional end, but I'm having trouble with the styling. In particular, it's very convenient to have tied the dialog location to Leaflet's 'L.Control.extend()' presets of top-right, bottom-center, etc., but it handicaps other potential placements.

Forming a DOM element with a script is a bit alien to me - am I correct that I'll need to update something in this section of L.control.geosearch.js if I want to append the '.leaflet-control-geosearch' element somewhere else, like a footer or sidebar?

Thanks again!

Akash Deep Singhal

unread,
Jun 13, 2013, 1:10:56 PM6/13/13
to leafl...@googlegroups.com
Hello Stephen, Sorry to bother you. But please could you help on the Autocompletion / suggestion thing that how i can add into it or when it will be added in the plugin.
Thanks and Regards,

Akash Deep Singhal,
Dept. Web Nominee,
Chemical Engineering,
Indian Institutes of Technology - Bombay

Federico Martín Alconada Verzini

unread,
Jul 29, 2013, 9:56:58 AM7/29/13
to leafl...@googlegroups.com
Any news about autocompletion functionality for searchbox??
Thanks!

Stephan Meijer

unread,
Jul 29, 2013, 10:09:48 AM7/29/13
to leafl...@googlegroups.com
Sorry to you all. I've been in a very busy period. I'll update the plugin soon, by merging some of the pull requests you guys already pushed back to me, and by adding some requested functionality.

I'll come back here soon! That's a promise.

Stefano Cudini

unread,
Sep 4, 2013, 2:38:30 PM9/4/13
to leafl...@googlegroups.com
hi

I'm creating an new demo for geocoding, using google coding api:
http://labs.easyblog.it/maps/leaflet-search/demos/google-geocoding.html
This plugin support autocomplete on tooltips menu (api requests over jsonp)

Solimyr

unread,
Oct 19, 2013, 10:13:41 AM10/19/13
to leafl...@googlegroups.com
Hi all,

I'm new to this world. I'm playing around with leaflet.js and I want to add a search button as in this demo (on the top of the page):


I have  a very basic problem. How could I "install" the plugin? Where I have to put the files? I have to download the zip file from the github (here) and after that?

Sorry for the newbie question...

Stefano Cudini

unread,
Oct 19, 2013, 10:30:45 AM10/19/13
to leafl...@googlegroups.com

Solimyr

unread,
Oct 19, 2013, 10:53:14 AM10/19/13
to leafl...@googlegroups.com
Thanks for the very fast answer! I have seen the example and this what I've done:
  • download the zip file from github;
  • copy the 'src' folder at the same level of my html file;
  • copy and paste the pieces of codes that I need.
Still not working, I suppose I've some error...This the code:

<HTML> 
     <HEAD> 
         <TITLE> First WebGIS </TITLE> 
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.6.4/leaflet.css" />
<link rel="stylesheet" type="text/css" href="style.css" />
 <!--[if lte IE 8]>
     <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.6.4/leaflet.ie.css" />
 <![endif]-->
                <script src="src/js/l.control.geosearch.js"></script>
                <script src="src/js/l.geosearch.provider.google.js"></script>
                <link rel="stylesheet" type="text/css" href="src/css/l.geosearch.css">
     </HEAD> 
     <BODY> 
          <P> </P>
<div id="map"></div>
                    <script src="http://cdn.leafletjs.com/leaflet-0.6.4/leaflet.js"></script>
                <script>
                  window.onload = function () { 
            
            function getURLParameter(name) {
            return decodeURI(
                (RegExp(name + '=' + '(.+?)(&|$)').exec(location.search)||[,])[1]
            );
            }

            var regionParameter = getURLParameter('region');
            var region = (regionParameter === 'undefined') ? '' : regionParameter;

            var cloudmadeUrl = 'http://{s}.tile.cloudmade.com/afda1fc8c23548c28eeb256f3e08707c/997/256/{z}/{x}/{y}.png', cloudmadeAttribution ='Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="http://cloudmade.com">CloudMade</a>', cloudmade = new L.tileLayer(cloudmadeUrl, {
                maxZoom :18,
                attribution: cloudmadeAttribution ,
            });

            var roads = new L.TileLayer.WMS("http://localhost:8082/geoserver/wms",{
                    layers:'sf:roads',
                    format:'image/png',
                    transparent:true
                });

             var water = new L.TileLayer.WMS("http://localhost:8082/geoserver/wms",{
                    layers:'topp:tasmania_water_bodies',
                    format:'image/png',
                    transparent:true
                });


             var map = new L.map('map', {
                center: [30.0,0.0],
                zoom:2,
                layers: [cloudmade, roads, water],
                zoomControl:true
             });
   
            new L.Control.GeoSearch({
            provider: new L.GeoSearch.Provider.Google({
                region: region
            })
            }).addTo(map);

                    };
                </script>
     </BODY> 
</HTML>

I don't think that I wrong the path of the fodler, or I have ? :)

Stefano Cudini

unread,
Oct 19, 2013, 11:20:12 AM10/19/13
to leafl...@googlegroups.com
any leaflet plugin needs Leaflet to be defined, then Leaflet must be defined before your plugin

Solimyr

unread,
Oct 19, 2013, 11:50:45 AM10/19/13
to leafl...@googlegroups.com
Sorry, didn't understand, could you please be clearer? Or please could give me an url to a documentation?

Thanks!
Message has been deleted

Solimyr

unread,
Oct 22, 2013, 10:16:36 AM10/22/13
to leafl...@googlegroups.com
Solved! I have to put these script:

<script src="leaflet.js"></script>

In the Head and not in body. I'm not so sure why! I found the solution looking at the example in the github webpage (here).

Thanks

On Tuesday, October 22, 2013 3:24:15 PM UTC+2, Solimyr wrote:
I was able to install it looking at the demo! Unfortunately now I get the search bar but if I search something nothing happens! 

Do you know where is my mistake? The code is the following:

<html><head> 
         <title> Locate </title> 
<link rel="stylesheet" href="leaflet.css">
 <!--[if lte IE 8]>
     <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.6.4/leaflet.ie.css" />
 <![endif]-->

<link rel="stylesheet" href="l.geosearch.css">
<script src="http://code.jquery.com/jquery-1.8.3.min.js"></script>

<script src="l.control.geosearch.js"></script>
<script src="l.geosearch.provider.google.js"></script>
<link rel="stylesheet" href="l.geosearch.css">



     </head> 
     <body> 
          <p> </p>
          <div id="map" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;" class="leaflet-container leaflet-fade-anim" tabindex="0"><div class="leaflet-map-pane" style="-webkit-transform: translate3d(0px, 0px, 0);"><div class="leaflet-tile-pane"><div class="leaflet-layer"></div></div><div class="leaflet-objects-pane"><div class="leaflet-shadow-pane"></div><div class="leaflet-overlay-pane"></div><div class="leaflet-marker-pane"></div><div class="leaflet-popup-pane"></div></div></div><div class="leaflet-control-container"><div class="leaflet-top leaflet-left"><div class="leaflet-control-zoom leaflet-control"><a class="leaflet-control-zoom-in" href="#" title="Zoom in"></a><a class="leaflet-control-zoom-out" href="#" title="Zoom out"></a></div></div><div class="leaflet-top leaflet-right"></div><div class="leaflet-bottom leaflet-left"></div><div class="leaflet-bottom leaflet-right"><div class="leaflet-control-attribution leaflet-control">Powered by <a href="http://leaflet.cloudmade.com">Leaflet</a></div></div><div class="leaflet-top leaflet-center"><div class="leaflet-control-geosearch leaflet-control"><input id="leaflet-control-geosearch-qry" type="text" placeholder="search for address..."><div id="leaflet-control-geosearch-msg" class="leaflet-control-geosearch-msg"><ul id="leaflet-control-geosearch-results"></ul></div></div></div></div><div class="leaflet-map-pane" style="-webkit-transform: translate3d(0px, 0px, 0);"><div class="leaflet-tile-pane"><div class="leaflet-layer"><div class="leaflet-tile-container leaflet-zoom-animated"></div><div class="leaflet-tile-container leaflet-zoom-animated"><img class="leaflet-tile leaflet-tile-loaded" style="height: 256px; width: 256px; left: 980px; top: 406px;" src="http://c.tile.cloudmade.com/afda1fc8c23548c28eeb256f3e08707c/997/256/13/4304/2940.png"><img class="leaflet-tile leaflet-tile-loaded" style="height: 256px; width: 256px; left: 724px; top: 406px;" src="http://b.tile.cloudmade.com/afda1fc8c23548c28eeb256f3e08707c/997/256/13/4303/2940.png"><img class="leaflet-tile leaflet-tile-loaded" style="height: 256px; width: 256px; left: 724px; top: 150px;" src="http://a.tile.cloudmade.com/afda1fc8c23548c28eeb256f3e08707c/997/256/13/4303/2939.png"><img class="leaflet-tile leaflet-tile-loaded" style="height: 256px; width: 256px; left: 980px; top: 150px;" src="http://b.tile.cloudmade.com/afda1fc8c23548c28eeb256f3e08707c/997/256/13/4304/2939.png"><img class="leaflet-tile leaflet-tile-loaded" style="height: 256px; width: 256px; left: 980px; top: 662px;" src="http://a.tile.cloudmade.com/afda1fc8c23548c28eeb256f3e08707c/997/256/13/4304/2941.png"></div></div></div><div class="leaflet-objects-pane"><div class="leaflet-shadow-pane"></div><div class="leaflet-overlay-pane"></div><div class="leaflet-marker-pane"></div><div class="leaflet-popup-pane"></div></div></div><div class="leaflet-control-container"><div class="leaflet-top leaflet-left"><div class="leaflet-control-zoom leaflet-bar leaflet-control"><a class="leaflet-control-zoom-in" href="#" title="Zoom in">+</a><a class="leaflet-control-zoom-out" href="#" title="Zoom out">-</a></div></div><div class="leaflet-top leaflet-right"></div><div class="leaflet-bottom leaflet-left"></div><div class="leaflet-bottom leaflet-right"><div class="leaflet-control-attribution leaflet-control"><a href="http://leafletjs.com" title="A JS library for interactive maps">Leaflet</a> | Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="http://cloudmade.com">CloudMade</a></div></div></div></div>
<script src="leaflet.js"></script>
<script src="https://maps.gstatic.com/intl/it_it/mapfiles/api-3/13/14/main.js"></script>
<script>


window.onload = function () { 

function getURLParameter(name) {
   return decodeURI(
       (RegExp(name + '=' + '(.+?)(&|$)').exec(location.search)||[,])[1]
   );
}

var regionParameter = getURLParameter('region');
var region = (regionParameter === 'undefined') ? '' : regionParameter;

var map = L.map('map').setView([45.202934, 9.137108], 13);
L.tileLayer('http://{s}.tile.cloudmade.com/afda1fc8c23548c28eeb256f3e08707c/997/256/{z}/{x}/{y}.png', {
    attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="http://cloudmade.com">CloudMade</a>',
    maxZoom: 18
}).addTo(map);
new L.Control.GeoSearch({
            provider: new L.GeoSearch.Provider.Google({
            region: region
            })
        }).addTo(map);

};
</script>
      
</body></html>

Thanks!

Stefano Cudini

unread,
Oct 22, 2013, 10:22:31 AM10/22/13
to leafl...@googlegroups.com
script tag can be inserted anywhere in the html page, but: Leaflet.js must be included before L.control.geosearch.js because L.control.geosearch.js use the L object


2013/10/22 Solimyr <giannic...@msn.com>

--
 
---
You received this message because you are subscribed to a topic in the Google Groups "Leaflet" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/leaflet-js/xSC34CQY_yw/unsubscribe.
To unsubscribe from this group and all its topics, send an email to leaflet-js+...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Stefano Cudini

unread,
Oct 22, 2013, 10:37:47 AM10/22/13
to leafl...@googlegroups.com
however, a good practice is to always insert the javascript in the bottom page, before </body>

read here:

P.S.
tratto da questo ottimo libro, c'è anche in italiano:

Solimyr

unread,
Oct 23, 2013, 4:38:18 AM10/23/13
to leafl...@googlegroups.com
Thanks!!!
Reply all
Reply to author
Forward
0 new messages