jQuery Store Locator Plugin
I can’t believe it’s been over a year since I first published my Google Maps store locator JavaScript code. I’ve had several requests for an updated version and that post has definitely received more traffic than any of my others. I’ve finally created a new version of the locator using Google Maps API version 3 and this time I’ve turned it into a full-on jQuery plugin. I re-worked almost everything in the code but I don’t think I’m going to go through function by function like I did in the last post. jQuery should make this store locator much easier to implement and I’ve included several options. Without further ado, here is the full documentation for the plugin:
jQuery Google Maps Store Locator Plugin
Files can be downloaded from GitHub and will be in the /dist directory
This jQuery plugin takes advantage of Google Maps API version 3 to create an easy to implement store locator. No back-end programming is required, you just need to feed it KML, XML, or JSON data with all the location information. How you create the data file is up to you. I originally created this for a company that didn’t have many locations, so I just used a static XML file. You will need to geocode your locations beforehand or use a geocoding API service if you want to try to do it on the fly. The reason for this is that all free geocoding APIs have strict limits that would easily be exceeded. In the end, you’re much better off storing the coordinates versus having to look them up for each location on each request.
A note on the distance calculation: this plugin currently uses a distance function that I found on the blog of Chris Pietschmann. Google Maps API version 3 does include a distance calculation service (Google Distance Matrix API) but I decided not to use it because of the current request limits, which seem somewhat low. For v2 I also tried experimenting with the Directions API to request distances but also found the limits to be too restrictive. So, the distance calculation is “as the crow flies” instead of a road distance calculation. However, if you use the inline directions option that does provide the distance that’s returned via the directions request.
Last, it’s very important to note that the plugin requires the Handlebars template engine. This separates the markup of the infowindows and location list elements so that they can easily be restructured. Handlebars pretty slick, will read Mustache templates, and the built-in helpers really come in handy. Depending on what your data source is, 2 of the 4 total templates will be used (KML vs XML or JSON) and there are options to set the paths of each template if you don’t want them in the default location. If you’re developing something for mobile devices the templates can be pre-compiled for even faster loading.
Options
It is much easier to maintain the current list of options on GitHub vs. a gigantic HTML table, which is why I’m now including the options.md file in the repository. If you need to view options for a previous version please view the old options page.
Usage:
Assuming you already have your locations.xml file set up in the current directory and the basic HTML copied from the example index file, the following would be the simplest usage example:
1. Include the css file (you’ll most likely want to make modifications to this beforehand):
<link rel="stylesheet" type="text/css" href="assets/css/storelocator.css">
2. Include jQuery if you don’t have it on your page already (the example below uses the Media Temple CDN but you can load it from wherever you’d like):
<script src="https://code.jquery.com/jquery-1.11.2.min.js"></script>
3. Include the latest version of Handlebars.js (this is now required)
<script src="assets/js/libs/handlebars.min.js"></script>
4. Create a new Google Maps API key and make sure to enable Google Places API Web Service, Google Maps Geocoding API and Google Maps Directions API for the project in the Google API Console after setting up the initial Maps key.
5. Include Google Maps API with your key. If you want to target a particular country add “®ion=” to the end of the URL followed by the country code.
<script src="https://maps.google.com/maps/api/js?key=yourkey"></script>
Region targeting example:
<script src="https://maps.google.com/maps/api/js?key=yourkey®ion=UK"></script>
6. Include the plugin file:
<script src="assets/js/plugins/storeLocator/jquery.storelocator.js"></script>
7. Apply the storeLocator plugin to the map-container div.
<script> $(function() { $('#bh-sl-map-container').storeLocator(); }); </script>
8. Make sure you have the basic form and map container HTML set up or copied from the example file.
Geocoding:
To geocode all your locations you can use a free or paid service or use the geocode.html that I included. This provides a basic form and will use the Google Maps API to give you the latitude and longitude of the location you input.
JSON (optional):
I’ve added JSON support as an option with version 1.2 of the plugin, which is completely optional. The JSON file included in the GitHub repository is just there as an example. The file was generated via PHP from a MySQL database. The database structure I used for the example is pictured in the following image:
Outputting the JSON from the database is extremely simple with PHP. Make the database connection with MySQLi and use something such as:
$results = $db->query("SELECT * FROM locations"); $locations = array(); foreach($results as $location){ array_push($locations, $location); } //Output JSON echo json_encode($locations);
Then you’d just set the dataLocation setting in the plugin directly to the PHP file and the dataType setting to json.
Support:
I’ll try to answer basic questions and create more examples but my time is limited.
- Demo example
- Modal window example
- Default location example
- HTML5 auto geocode example
- KML example
- JSON example
- Maximum distance example
- No form tags example
- Bootstrap (responsive) example
- Category filtering example
- Custom category markers example
- Inline directions example
- Name search example
- Pagination example
- Raw data example
- Query string example
- XML format example for location data
Tutorials
- Using the jQuery Store Locator with thousands of locations
- Using query string parameters with the jQuery Store Locator
Cardinal Store Locator
Donations
Some people have asked to donate. Feel no obligation but if you want to my Paypal email is bjorn2404@gmail.com and I also have a Bitcoin address set up: 17ueYyfaxCyEXedecVnr3w7GjM9PJD4CHj
Special thanks
My initial motivation for creating this jQuery plugin was a custom implementation request of my older JavaScript locator for Phin & Phebes Ice Cream. If you’re on the east coast be sure to seek out a pint.
Oops! We could not locate your form.
Hi,
how to change the marker icon?
same this
https://thumbs.dreamstime.com/z/set-z-alphabet-pin-marker-flat-icons-lon-long-shadow-gps-map-35937202.jpg
Thank you!
Hi,
Thank you for the plugin.
In the plugin there is a map creation of two times. one is in _start function, Second one is processData function (in the latest version there is one more creation that is emptyResult function) . Instead using map creation on all these functions, can’t we create globally one time and use to avoid performance issue on loading more json data?
How to show marker to autogeocode
Greetings,
I have a request for the jQuery map plugin to pass up to 5 small icons for a location’s service grading. The small icons should post to the right of the location title in the ul list. Is this possible with your build and what would it take to modify?
The code as is will not pass image tags. Any help appreciated.
Thanks in advance,
James
Had an issue of not being able to control the zoom when returning only one result (zoomed in too far). Added this after the map create:
google.maps.event.addListenerOnce(_this.map, ‘bounds_changed’, function () { this.setZoom(Math.min(17, this.getZoom())); });
actually the best way to do this is to alter the function at line 2924
if ((_this.settings.fullMapStart === true && firstRun === true && _this.settings.querystringParams !== true) || (_this.settings.mapSettings.zoom === 0) || (typeof origin === ‘undefined’) || (distError === true)) {
if (bounds.getNorthEast().equals(bounds.getSouthWest())) {
var extendPoint1 = new google.maps.LatLng(bounds.getNorthEast().lat() + 0.001, bounds.getNorthEast().lng() + 0.001);
var extendPoint2 = new google.maps.LatLng(bounds.getNorthEast().lat() – 0.001, bounds.getNorthEast().lng() – 0.001);
bounds.extend(extendPoint1);
bounds.extend(extendPoint2);
}
_this.map.fitBounds(bounds);
}
Hi Bjorn,
I’ve created API key and enabled the 3 APIs, then I’ve replaced my code with the “yourkey” , as a result, no map is showing. But I see the request on the Google Console. If I remove “?key=yourkey” map begin to appear.
Hi Bjorn, I’ve solved the problem. You’ve missed the fourth API key to enable which is “Google Maps JavaScript API” when I enable this API too everything turned to normal.
I would like to use your plugin in my angular 2 or 4 based application. How can I implement it ?
Hi Bjorn,
I’ve followed your instructions except the API key issue I’ve experienced very weird issue. I’ve used Default location example (diplikaya.com/dist/default-location-example.html) page gives “Unable to find address” error however If I visit the “Default location example” page at your site (bjornblog.com/storelocator/v2/default-location-example.html) the map is starting to work for a while on my server. Can you suggest anything?
Thanks in advance.
Hello and congratulation for this great plugin.
Iwould like to retrive the ID of clicked location but i don’t uderstand how to use the callback functions…
I try this but it tell me always undefined
$(‘#bh-sl-map-container’).storeLocator({
callbackListClick: function(selectedMarker){
alert(‘you clicked: ‘+ selectedMarker.id);
}
});
Thank you!
FR
With ID I mean the id in the json, not the array id
How add location duration
Hi,
First thank you for your great plugin.
I have integrated the plugin on our website but we doubled the list of locations when you return to the map after updating the order of real estate by AJAX.
You can see what happens if you enter here:
http://www.rentalscollection.com/en/neighborhoods/page_1/donostia-san-sebastian/2/la-concha-beach.php
Press VIEW MAP (11 apartments) then any of the other order tabs and again VIEW MAP and the property list is duplicated the second time (22 apartments). Any help please? Thank you
Hi I have a problem, I have 3 records on the xml that has the same lat and long, and it only shows 1 marker on the map, how can I fix that issue?
Hey there,
Your script is working nice, however, I was looking at a way to improve the search function.
Right now, you can say it should only filter/search on 1 field like ‘name’ or ‘title’.
And it seems to be working on complete words only, and not parts of words, so when I enter ‘ocation’ it will not find anything, however when I enter ‘location’ it will.
So, it looks like the filtering is done in this part:
!(new RegExp(filters[k].join(”), ‘i’).test(data[k].replace(/([^\x00-\x7F]|[.*+?^=!:${}()|\[\]\/\\])/g, ”)))
Any idea how to change the behaviour???
Two questions:
Can you disable the map and just show the list?
How do you adjust what XML data is displayed in the list?
The Google Maps API specifically forbids use of the Geocoding API without displaying a map.
To update the data in the list you want to modify the Handlebars template in /assets/js/plugins/storeLocator/templates/
I want to learn more about the templates and the tokens they use. Would you point me in the right direction? I want to know if could loop through and array somehow.
Nice to see that this project is still alive after all these years 🙂 Lot of work have been done, you’re incredible !
I am trying to get this to work inside of a code igniter application, anyone struggle with that already and have some tips?
I am getting this error, Uncaught TypeError: $(…).storeLocator is not a function
I had to rearrange some of my pre existing scripts and it is working now.
Is there any way to use address components that consist of multiple fields such as address1, address2, city, state and zip instead of one field?
If you have it separate in your data you can set up filters for it. For example, please see the categories example that has city and zip filters: https://bjornblog.com/storelocator/v2/categories-example.html
If the json file contain special characters, such as japanese, chinese characters, even the html show correctly, but the js cannot search anything, the problems seem if you filter by country or city. Are there any way to solove it? Thx.
Is there a way I can only restrict the text box to ZIPCODE and not use address?
Hi! Great Pluggin!
Any idea how can i zoom in the map with an external button?
thanks!
Max
Thoughts on how to update this to use OSM given the new Google Maps pricing changes?
At this point I have no plans to do this. Using the Google Maps API is still free up to a certain number of requests that should work for the average site. If they further tighten the restrictions I’ll consider pivoting but at that point it will likely all be redone with vanilla JS or React or Vue.
Is it possible to implement the search call to go through a .ajax() call and return a JSON object?
I love the plugin. But I have to admit, it sucks that you took away the option to set the directions container. Sometimes you only have one location so you don’t need the list. Was nice being able to decide where the directions would be placed. Going back to the older version. I don’t really see the benefits of the new approach.
Can you explain further about what you are referring to? I don’t remember removing anything related to this.
This is exactly what I’ve been looking for! Thank you! How would I show the map automatically when the page loads?
The fullMapStart setting. All the settings are documented.
Great Plugin
Hello Bjorn,
Good plugin!! I hope you have some small time to answer 🙂 I’m working with it on my iPad and I’m wondering how you will disable the locations list panel so you will get only the map visible. Is there any property for that? Keep up the good working!
Greets,
Mark
For an easy and quick method you could just hide the list with CSS.
Hey Bjorn, is there any way to disable it from jquery.storelocator.js so it will not be generated at all? It takes much cpu load. I thought i did find it by that way somewhere.
Thanks
800 Washington Ave SE, Minneapolis, MN 55414
560 W 79th St, Chanhassen, MN 55317
It is noted that for this plugin: The distance calculation is “as the crow flies” instead of a road distance calculation.
However, if you use the inline directions option that does provide the distance that’s returned via the directions request.
I used Inline directions example and it doesn’t match what shows in google maps? what am i missing.
16.96 miles
Clicking on Directions:
Google maps
23.3 miles or
22.4 miles
To minimize directions API requests the information is only available after clicking the directions links.
Hi Bjorn,
Do you have an example showing the ajaxdata option functionality by any chance?
The ajaxData setting allows you to send data along with the locations request, it’s not for sending raw location data to the plugin – that can be done with the dataRaw setting (I realize now that it’s a little confusing). The main thought behind ajaxData is to allow tracking of custom parameters but there might be other good uses as well. For example, if you wanted to start logging what people were searching for you could grab the user input, use ajaxData to send it to a back-end file, sanitize the value, and then send it to a database. My post about using the plugin with thousands of locations has some PHP code that grabs the origLat and origLng that is sent over by default.
Is there any way to reload the locations (I’m using json dataRaw) without doing a destroy on the whole container and building the map from scratch?
I’m using external filtering of my location array and external filtering inputs and need to just pass the new locations and update the map and list.
Thanks in advance,
Christian
hi Bjorn,
Nice plugin. But whenever I tried with postal code (in the search box) i8ts not working.I’m using Australia region instead of UK. I changed the value in location.json.It would be really helpful for me if u guide me through this.Thanks in advance
Is there a way to make sure it is using walking distance in the distance calculation? Thanks
Hi Bjorn, I have been using the map for years and working great, but now I noticed that when I type the zip code I always type for testing (10010, which is Manhattan), it takes me to a complete different place.
So I came here and tried your demo and it’s happening the same thing.
Do you have any idea what could be the reason?
Actually, I wasn’t able to reproduce it with other zip codes, just with the one I normally use for testing.
I guess I will have to change my habits and test with a different one 🙂
Last comment: if I try 10010 in double quotes, it works. This is new to me.
Your project is awesome!
Good job!
I have a question: in the JSON example how can I search by address instead of latitude and longitude?
Thank you for your time
I’m getting the words “For Development Purposes Only” over a greyed out Google map. What is this and how is it fixed?
Love the plugin! Have been using it for years. How do I send you a donation?
Am using json to populate the location, however I need to populate 35 different location and it takes and displays only 26 which is A to Z, is there a work around or a way to use numbers instead of alphabets?
Hi, Loving you’re store locator…
I’m a newbie to jQuery, and would appreciate your quidance… I’m also happy to make a contribution to have a few amendments if not already there..
Would it be possible to have a “popup” showing the name of the marker when you hover over it..
Would it be possible to define the start location for travel directions by picking a location from the listing as opposed to using a geocoded position.
Many thanks.
Hello,
first of all congratulations for the excellent plugin
I would like to ask you if it is possible to obtain the number of items contained in the list because I would like to add above the list of items “We found X solutions”
Thanks
Giovanni
Hi Bjorn,
How do I set a custom selected marker image? I see the property in the storelocator.js file but I’m not sure how to access it
Hello,
first of all congratulations for the excellent plugin.
I’m trying to implement into my website, but i’m always get 2 error
1. Unable to find address
2. Reverse geocode was not successful for the following reason: REQUEST_DENIED
For the poin 1, where i can change the position of the main location, i’m in Italy
For point 2 it is strange, because I have the API key working perfectly on this site
Can you give me some advise to solve this problems
Thanks
Joe
Sir, can you please explain how can I show the user location using a marker on the map along with the nearest stores? is it going to fit in if the user is from somewhere else like from another country?
This module is awesome but i have litle question , i use a filter for everything country , city , postcode , some another data from mysql database and i want if i open a page every location is loading without i add adress or zip code before. This is possible ?
hello , how to add input type=”text” taxonomyfilter in javascript accepted only checkbox , radio and selected 🙂
Hello,
Thanks for this great code.
I’m having trouble since last update; some addresses does not show up anymore.
I’ve enabled the “debug” option but I cannot see any error.
How can I find the cause?
Best regards,
I also try to use in shopify but and it show “$(…).storeLocator is not a function” too.
I test well locally.
Would you help to sove it?
Thank you very much.
Within the last day or two the storelocator script has started to produce errors.
“I have been getting a slew of calls from way outside of our servicing area….. Utah, Pennsylvania, New York, Virginia, Utah…. The customers all state they are getting our number off the dealer locator? I went in and put in a zip code for PA and Alaska came up.”
Zip: 45365 produces results on maps.google.com. On the store locator that zip is posting the error: Unable to find address
I tested 45365 in your demo and it is producing the Unable to find address error also.
Store locator has been working without issues for years. It’s an old version v2.7.4, a clean current version installation would require many mods.
Other zips tested appear to be loading as they should.
Is this problem a Google api issue?
Host did an Apache update and I suspect it may be causing the issue.
Apache HTTP Server 2.4.55
————————-
Throughout the next two weeks, all XXX Networks servers will
be upgraded to Apache HTTP Server 2.4.55. This is a minor
upgrade and we do not expect it to be noticeable. If you do
experience problems that you believe may be related to this
upgrade, please do not hesitate to contact us.
(Posted On: Feb 14, 2023, 12:37 PM Eastern)