DotNetNuke: Store Locator

Live example: [Click Here]

Download: Store Locator_01.00.00_Install.zip (this link contains the install and source) (note: If using DNN4 install and run LinqPrep first. If using DNN5 follow these directions first)

Store Locator is a DNN4/DNN5 module that allows the administrator to enter unlimited locations that are automatically Geo-coded. Each module instance has it's own list of locations and Google API key. The Module is fully integrated in DNN and does not use IFrames. The Module also uses Linq to SQL.

Source code:

The Store Locator Module

This module is based on Donn Felker's Store Locator project. He writes about the details of the project here. This module was suppose to be an "easy port to DNN" but the Google Map API uses a lot of JavaScript and what is normally strait-forward for a standard ASP.NET application can get complex for DNN.

The Module

After installing the module...

You will be instructed to enter your Google Maps API key in the module Settings.

Click the Settings icon...

Scroll to the bottom of the Settings page and expand the Google API Key Settings section and enter your Google API Key and click Update.

Click here to get your Google API key. Note: This key must be created for the web address it will be used on. If you have multiple portals with different addresses you can set a Google API key for each instance of the module.

Click the Edit Locations link to enter locations.

After you enter each address and click the Insert button, it is automatically Geo-coded and the Latitude and Longitude is stored in the database.

When a visitor enters a full address, or just a zip code, the module will display the closest locations. Clicking on the location icons will display the details and a link to directions.

The Code

All the data is stored in a simple table called ADefWebserver_Locations.

The Linq to SQL class contains the ADefWebserver_Locations table and the GetNearbyLocations function that is mapped to the stored procedure of the same name. This is the stored procedure that creates the list of nearby locations based on the Longitude and Latitude.

The GetNearbyLocations function in the Linq to SQL class is created by dragging the stored procedure from the Solution Explorer and dropping it on the ADefWebserver_Location table in the Linq to SQL designer. This causes the Return Type of the GetNearbyLocations function to be of type ADefWebserver_Location.

We are then able to pass parameters and call the stored procedure with code such as this and get a List of ADefWebserver_Location objects:

        #region GetLocationData
        private List<ADefWebserver_Location> GetLocationData(GoogleGeoCoder.Coordinate coordinate)
        {
            StoreLocatorDALDataContext StoreLocatorDALDataContext = new StoreLocatorDALDataContext();

            return StoreLocatorDALDataContext.GetNearbyLocations(Convert.ToDouble(coordinate.Latitude), 
               Convert.ToDouble(coordinate.Longitude), Convert.ToInt32(distanceDropDown.SelectedValue), 3961, ModuleId).ToList();
        }
        #endregion
Geo-coding an address is actually very simple. The WebClient object is used to make a simple call to Google:
            public static Coordinate GetCoordinates(string address, string googleApiKey)
            {
                Coordinate objCoordinate;
                WebClient client = new WebClient();
                Uri uri = GetGeocodeUri(address, googleApiKey);

                /*  The first number is the status code, 
                 * the second is the accuracy, 
                 * the third is the latitude, 
                 * the fourth one is the longitude.
                 */

                string[] geocodeInfo = client.DownloadString(uri).Split(',');

                if (Convert.ToDecimal(geocodeInfo[2]) > 0)
                {
                    objCoordinate = new Coordinate(Convert.ToDecimal(geocodeInfo[2]), Convert.ToDecimal(geocodeInfo[3]));
                }
                else
                {
                    objCoordinate = new Coordinate(Convert.ToDecimal(0), Convert.ToDecimal(0));
                }

                return objCoordinate;
            }

JavaScript and DNN

The challenge with this project is displaying the Google map. Donn Felker explains how his code retrieves the map and builds the icons (he writes about the details of the project here), however, the main challenge that you have with DotNetNuke is that you do not know where your module will be placed on the page. With DotNetNuke everything is dynamic.

The Google Map API requires that you indicate the DIV tag in the .html page that the map will be injected into. This DIV must have a unique name. You can use a ASP.NET Panel control that will create a unique DIV at run-time. However, it is impossible to know in advance what the name of the DIV tag will be.

First, we created the GMapjs.txt file. This file contains the JavaScript that Donn Felker wrote (this also allows us to easily alter the JavaScript if needed). In his original script, he set the name of the DIV to "map". In the GMapjs.txt file we replaced it with [MAPDIV].

var map = new GMap2(document.getElementById("[MAPDIV]"));
The text file is read by this method:
        #region GetTextFile
        private String GetTextFile(string PathandScript)
        {
            string strTextFile;
            StreamReader reader = new StreamReader(PathandScript, System.Text.Encoding.Unicode);
            strTextFile = reader.ReadToEnd();
            reader.Close();
            reader = null;
            return strTextFile;
        }
        #endregion
And the name of the DIV is replaced in the file by this method:
        #region GetGoogleMapload
        private string GetGoogleMapload()
        {
            string strAppBase = Server.MapPath(this.TemplateSourceDirectory + @"\..\..\");

            string strFileNameAndPath =
                String.Format("{0}DesktopModules\\StoreLocator\\JavaScript\\GMapjs.txt", strAppBase);

            string strImagesPath = String.Format(@"http://{0}/{1}", 
                Request.Url.Host, this.TemplateSourceDirectory);

            string strTextFile = GetTextFile(strFileNameAndPath);

            strTextFile = strTextFile.Replace("[MAPDIV]", this.map.ClientID);
            strTextFile = strTextFile.Replace("[MAPLOCATION]", strImagesPath);

            return strTextFile;
        }
        #endregion
"this.map.ClientID" is the current value of the Panel that we want the Google Map injected into. Also note that a replacement for [MAPLOCATION] is also made so that the JavaScript will know where the images are that display the location points on the map.

An ASP.NET Literal control is used to display the contents of the now altered JavaScript:

lrlGoogleMap.Text = GetGoogleMapload();
The use of the Literal control is important. The JavaScript has to be parameterized so it needs to be placed directly in the code. The Literal control will not alter the JavaScript so the JaveScript functions correctly.

The following line in the Page_Load method calls the JavaScript:
Page.ClientScript.RegisterStartupScript(this.GetType(), string.Format("GoogleMap{0}", Convert.ToString(ModuleId)), "GoogleMapload();", true);
And the map displays.

Note:  To work correctly, the module only allows one instance of the module to be placed on a single page. This is because there are more elements of the JavaScript that should be parameterized. If you have a need for more than one map on a page you can add the additional parameterization.

Summary

This code should be easily adaptable for your own projects. This project demonstates a solution to most of the problems you will encounter in implementing modules that use custom JavaScript.

 

[Back to: The ADefWebserver DotNetNuke HELP WebSite]

 


Buy DotNetNuke Modules from Snowcovered

 DotNetNuke Powered!DotNetNuke is a registered trademark of DotNetNuke Corporation.