Search Articles


Sort By
  

Article Categories

Authors & MVPs

Kelly Ford

Introducing DNNDev University

The new DNNDev University doesn't have a winning football team. It is built on people - you and I and everyone who uses DotNetNuke and XMod Pro.

XModPro

Plotting XMod Pro Data On Google Maps

Some time ago while working with the original XMod I wanted to plot yacht positions, marinas and anchorages from XMod on a Google map. At the time I found Scott Jennings had already done this with MarinaPal. Scott was kind enough to post his Javascript and XMod forms and templates on his site. You can still find them here. And you can find his Geocoder which is useful for getting the latitude and longitude data in decimal format just by clicking on the map. MarinaPal Geocoder here.

I began to experiment with plotting XMod data onto Google Maps and then XMod Pro came along. Being very happy that XMod Pro was available and realizing immediately that my total devotion to XMod 5.1 was going to end I decided to modify Scott’s code to work with XMod Pro. So I built a full working demo as an example for a project I had in mind.

Since I put this together things have moved on a great deal and the Javascript side is much easier. JQuery has arrived and there are now plug-ins that make Google maps integration a whole lot easier and quicker. When I find the time I will build a jQuery version but for now you can build the demo with the following.

First get an API key from Google for your map web site.

Then run this SQL into your database. This builds a couple of tables for the data.

-- Script to create Yacht Haven demo project
-- A. Beare, Caraway Design, Nov 2010
-- http://www.carawaydesign.com

IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[CD_Havens]') AND type in (N'U'))
DROP TABLE [dbo].[CD_Havens]

GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[CD_Havens](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Type] [int] NOT NULL,
[Lat] [nvarchar](100) NOT NULL,
[Long] [nvarchar](100) NOT NULL,
[Title] [nvarchar](100) NULL,
[Description] [nvarchar] (500) NULL,
[Country] [nvarchar](100) NULL,
[Region] [nvarchar](100) NULL,
[email] [nvarchar](100) NULL,
[web] [nvarchar](100) NULL,
[phone] [nvarchar](100) NULL,
[CreatedBy] [nvarchar](100) NOT NULL,
[LastUpdatedBy] [nvarchar](100) NOT NULL
)
GO


IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[CD_Havens]') AND type in (N'U'))
DROP TABLE [dbo].[CD_HavenType]
go

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[CD_HavenType](
[ID] [int] NOT NULL,
[HavenType] [nvarchar](50) NOT NULL
)
GO


-- clear out havens
delete from CD_havens
go

-- insert some test data
INSERT INTO [cd_havens] ([Type],[Lat],[Long],[Title],[Description],[Country],[Region],[email],[web],[phone],[CreatedBy],[LastUpdatedBy])VALUES(2,'40.03832653067254','4.124722480773926','Ses Salines','Anchorage off Ses Salines village','Spain','Minorca: Balearics','[email protected]','http://www.carawaydesign.com','+34444444444444','host','host')
INSERT INTO [cd_havens] ([Type],[Lat],[Long],[Title],[Description],[Country],[Region],[email],[web],[phone],[CreatedBy],[LastUpdatedBy])VALUES(1,'50.723','-1.7601','Christchurch','Shallow harbour','United Kingdom','Dorset','[email protected]','http://www.carawaydesign.com','+44 1202 49999','host','host')
INSERT INTO [cd_havens] ([Type],[Lat],[Long],[Title],[Description],[Country],[Region],[email],[web],[phone],[CreatedBy],[LastUpdatedBy])VALUES(3,'-46.8991466269853','168.12596797943115','Half Moon Bay Yacht Storage','Half Moon Bay','New Zealand','Stewart Island','[email protected]','http://www.carawaydesign.com','+44444444444','SuperUser Account','SuperUser Account')
INSERT INTO [cd_havens] ([Type],[Lat],[Long],[Title],[Description],[Country],[Region],[email],[web],[phone],[CreatedBy],[LastUpdatedBy])VALUES(2,'61.02104800773813','-149.9688720703125','Anchorage','An anchorage near Anchorage!','USA','Alaska','','','','SuperUser Account','SuperUser Account')
INSERT INTO [cd_havens] ([Type],[Lat],[Long],[Title],[Description],[Country],[Region],[email],[web],[phone],[CreatedBy],[LastUpdatedBy])VALUES(4,'-20.96143961409684','-137.63671875','The Bounty','Position of the Bounty of 1st August 1780','South Pacific','nr Friendly Islands','','','','SuperUser Account','SuperUser Account')

-- clear out haven types
delete from CD_haventype

-- insert some haven types
insert into CD_haventype (id,HavenType) values (1,'Port')
insert into CD_haventype (id,HavenType) values (2,'Anchorage')
insert into CD_haventype (id,HavenType) values (3,'Storage Ashore')
insert into CD_haventype (id,HavenType) values (4,'Waypoint')

Go

Then, in XMod Pro create a side bar list with the following template:

<xmod:template addroles="Administrators" editroles="Administrators" deleteroles="Administrators">

<listdatasource commandtext="SELECT h.ID, ht.HavenType, h.Lat, h.Long, h.Title, h.Description, h.Country, h.Region, h.Email, h.Phone, h.Web, h.CreatedBy, h.LastUpdatedBy FROM CD_Havens h inner join CD_HavenType ht on h.Type=ht.ID order by h.ID" />

<headertemplate>
<a name="HeaderTop"></a>
<div width="150px" height="40px" style="color:black;background-color:white;padding-bottom:10px;font-family:Georgia;font-size:14px"><strong>Click an Item</strong></div>

</headertemplate>

<itemtemplate>

<script type="text/javascript">
var i = i + 1;
x[i] = [[Lat]];
y[i] = [[Long]];
d[i] = '<table><tr><td>[[Title]]</td></tr><tr><td>[[Description]]</td></tr><tr><td>[[Country]]</td></tr><tr><td>[[Region]]</td></tr><tr><td>[[Email]]</td></tr></table>';
document.write('<div style="padding-bottom:8px;color:black;background-color:white" width="150px" onclick="myGclick(' + i + ');">')
</script>

<strong>
<table>
<tr><td colspan="2"><a href="#HeaderTop"><div style="color: #a41d21;font-size: 13px">[[Title]]</div></a></td></tr>
<tr><td colspan="2">[[Description]]</td></tr>
<tr><td>[[Country]]</td><td>[[Region]]</td></tr>
</table>

</div>


<xmod:scriptblock scriptid="GoogleMapScripts" registeronce="true" blocktype="ClientScript">
<script src="http://maps.google.com/maps?file=api&amp;v=2.x&amp;key=ABQIAAAAHrao_r7BKX4cQI0SxCQVHxRXbr2uTTbz5TwhEXAt1Cz65pgUPxQJAHBbHO1MuQeh5aRNkFOL-Ozptw" type="text/javascript"></script>
<script type="text/javascript">
//<![CDATA[

var map = null;
var geocoder = null;
var x=new Array()
var y=new Array()
var d=new Array()
var myGclick = [];
var gmarkers = [];

// This function picks up the click and opens the corresponding info window
myGclick = function myGclick(i) {
GEvent.trigger(gmarkers[i], "click");
}

oldLoad = window.onload;
window.onload = function load(){
if(oldLoad){
oldLoad();
}
if (GBrowserIsCompatible()) {

var map = new GMap2(document.getElementById("map"));
map.setCenter(new GLatLng(40, -98), 3);
map.addControl(new GLargeMapControl());
map.addControl(new GMapTypeControl());
map.addControl(new GOverviewMapControl());

// Creates a marker at the given point with the given number label
function createMarker(point, d) {
var marker = new GMarker(point);
GEvent.addListener(marker, "click", function() {
marker.openInfoWindowHtml(d);
});
// save the info we need to use later for the side_bar
gmarkers[i] = marker;
return marker;
}

for (var i = 0; i < 999; i++) {
var point = new GLatLng(x[i],
y[i]);
if ((x[i] == undefined)){break}
map.addOverlay(createMarker(point, d[i]));
}

}
}

//]]>
</script>
</xmod:scriptblock>

</itemtemplate>

<footertemplate>

</footertemplate>
<noitemstemplate>
<strong>nothing in table</strong>
</noitemstemplate>

<detailtemplate>
</detailtemplate>

</xmod:template>

You will have to edit the code above to add your new Google API key.

Then add an ordinary DNN text/html module to the page. Edit the module text and switch to source view and put the following to the box.

<div style="width: 500px; height: 400px;" id="map">&#160;</div>

This is where the map will be shown. You can also use an XMod Pro form or template to show the map.

There is also a list template and form to add/edit the list of points to plot.  Data list template:

<xmod:template>

<ListDataSource commandtext="SELECT h.ID, ht.HavenType, h.Lat, h.Long, h.Title, h.Description, h.Country,
h.Region, h.Email, h.Phone,
h.Web, h.CreatedBy,
h.LastUpdatedBy
FROM CD_Havens h
inner join CD_HavenType ht on h.Type=ht.ID" />

<deletecommand commandtext="DELETE FROM CD_Havens WHERE ID = @HavenID" id="HavenDelete">
<parameter name="HavenID" alias="HavenID" /></deletecommand>


<HeaderTemplate>


<table width="100%" border="0" cellspacing="4" cellpadding="4">
<tr>
<td class="Normal">
<strong>Type</strong>
</td>
<td class="Normal">
<strong>Latitude</strong>
</td>
<td class="Normal">
<strong>Longitude</strong>
</td>
<td class="Normal">
<strong>Title</strong>
</td>
<td class="Normal">
<strong>Description</strong>
</td>
<td class="Normal">
<strong>Country</strong>
</td>
<td class="Normal">
<strong>Region</strong>
</td>
<td class="Normal">
<strong>Email</strong>
</td>
<td class="Normal">
<strong>Phone</strong>
</td>
<td class="Normal">
<strong>Web</strong>
</td>
</tr>
</HeaderTemplate>
<ItemTemplate>

<tr>
<td class="Normal">[[HavenType]]</td>
<td class="Normal">[[Lat]]</td>
<td class="Normal">[[Long]]</td>
<td class="Normal">[[Title]]</td>
<td class="Normal">[[Description]]</td>
<td class="Normal">[[Country]]</td>
<td class="Normal">[[Region]]</td>
<td class="Normal">[[Email]]</td>
<td class="Normal">[[Phone]]</td>
<td class="Normal">[[Web]]</td>

<td class="Normal"><xmod:editlink text="Edit..." id="HavenEDIT">
<parameter name="HavenID" value='[[ID]]' />
</xmod:editlink>
<xmod:deletelink text="Delete" id="HavenDelete" onclientclick="confirm('delete?');">
<parameter name="HavenID" value='[[ID]]' />
</xmod:deletelink>

</td>
</tr>

</ItemTemplate>


<FooterTemplate>
</table>
<xmod:addbutton text="add new" />

</FooterTemplate>
<NoItemsTemplate>
<div>There is no data: to add a record click the button</div>
<xmod:addbutton text="add new" />
</NoItemsTemplate>

</xmod:template>

Add edit forms for map data:

<addForm >
<submitcommand commandtext="INSERT INTO CD_Havens (Type,Lat,Long,Title,Description,Country,Region,email,web,phone,CreatedBy,LastUpdatedBy)
VALUES (@HavenType,@Lat,@Long,@Title,@Description,@Country,@Region,@email,@web,@phone,@CreatedBy,@LastUpdatedBy)"/>

<controldatasource id="HavenTypeListAdd" commandtext="SELECT HavenType, ID FROM CD_HavenType ORDER BY HavenType ASC" />

<SelectCommand CommandText="SELECT @lub AS LastUpdatedBy, @cb as CreatedBy">
<parameter name="lub" value='[[User:DisplayName]]' />
<parameter name="cb" value='[[User:DisplayName]]' />
</SelectCommand>

<div style="padding-bottom:3px"><label target="txtHavenTypeAdd" text="Haven Type" class="NormalBold" width="100px" />
<DropDownList ID="txtHavenTypeADD" DataSourceID="HavenTypeListAdd" DataField="HavenType" DataType="int32" DataTextField="HavenType" DataValueField="ID" /></div>

<div style="padding-bottom:3px">
<label target="txtLat" text="Latitude" class="NormalBold" width="100px" />
<textbox id="txtLat" datafield="Lat" datatype="string" />
</div>
<div style="padding-bottom:3px">
<label target="txtLong" text="Longitude" class="NormalBold" width="100px" />
<textbox id="txtLong" datafield="Long" datatype="string" />
</div>
<div style="padding-bottom:3px">
<label target="txtTitle" text="Title" class="NormalBold" width="100px" />
<textbox id="txtTitle" datafield="Title" datatype="string" />
</div>
<div style="padding-bottom:3px">
<label target="txtDescription" text="Description" class="NormalBold" width="100px" />
<textbox id="txtDescription" datafield="Description" datatype="string" />
</div>
<div style="padding-bottom:3px">
<label target="txtCountry" text="Country" class="NormalBold" width="100px" />
<textbox id="txtCountry" datafield="Country" datatype="string" />
</div>

<div style="padding-bottom:3px">
<label target="txtRegion" text="Region" class="NormalBold" width="100px" />
<textbox id="txtRegion" datafield="Region" datatype="string" />
</div>

<div style="padding-bottom:3px">
<label target="txtEmail" text="Email" class="NormalBold" width="100px" />
<textbox id="txtEmail" datafield="Email" datatype="string" />
</div>

<div style="padding-bottom:3px">
<label target="txtWeb" text="Web Site" class="NormalBold" width="100px" />
<textbox id="txtWeb" datafield="Web" datatype="string" />
</div>

<div style="padding-bottom:3px">
<label target="txtPhone" text="Phone" class="NormalBold" width="100px" />
<textbox id="txtPhone" datafield="Phone" datatype="string" />
</div>
<div style="padding-bottom:3px">
<label target="txtCreatedBy" text="Created By" class="NormalBold" width="100px"/>
<textbox id="txtCreatedBy" datafield="CreatedBy" datatype="string" readonly="true" />
</div>

<div style="padding-bottom:3px">
<label target="txtLastUpdatedBy" text="Last Updated By" class="NormalBold" width="100px"/>
<textbox id="txtLastUpdatedBy" datafield="LastUpdatedBy" datatype="string" readonly="true" />
</div>

<div style="padding-bottom:3px">
<addbutton text="Add"/>
<cancelbutton text="Cancel"/>
</div>

</addForm>


<editForm >
<submitcommand commandtext="UPDATE CD_Havens SET [email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected] WHERE [email protected]" />
<selectcommand commandtext="SELECT ID as HavenID,Type,Lat,Long,Title,Description,Country,Region,Email,Web,Phone,CreatedBy,LastUpdatedBy FROM CD_Havens WHERE [email protected]"/>

<controldatasource id="HavenTypeListEdit" commandtext="SELECT HavenType, ID FROM CD_HavenType ORDER BY HavenType ASC" />

<div style="padding-bottom:3px"><label target="txtHavenTypeEdit" text="Haven Type" class="NormalBold" width="100px" />
<DropDownList ID="txtHavenTypeEdit" DataSourceID="HavenTypeListEdit" DataField="HavenType" DataType="int32" DataTextField="HavenType" DataValueField="ID" /></div>

<div style="padding-bottom:3px">
<label target="txtLatEdit" text="Latitude" class="NormalBold" width="100px" />
<textbox id="txtLatEdit" datafield="Lat" datatype="string" />
</div>
<div style="padding-bottom:3px">
<label target="txtLongEdit" text="Longitude" class="NormalBold" width="100px" />
<textbox id="txtLongEdit" datafield="Long" datatype="string" />
</div>
<div style="padding-bottom:3px">
<label target="txtTitleEdit" text="Title" class="NormalBold" width="100px" />
<textbox id="txtTitleEdit" datafield="Title" datatype="string" />
</div>
<div style="padding-bottom:3px">
<label target="txtDescriptionEdit" text="Description" class="NormalBold" width="100px" />
<textbox id="txtDescriptionEdit" datafield="Description" datatype="string" />
</div>
<div style="padding-bottom:3px">
<label target="txtCountryEdit" text="Country" class="NormalBold" width="100px" />
<textbox id="txtCountryEdit" datafield="Country" datatype="string" />
</div>

<div style="padding-bottom:3px">
<label target="txtRegionEdit" text="Region" class="NormalBold" width="100px" />
<textbox id="txtRegionEdit" datafield="Region" datatype="string" />
</div>

<div style="padding-bottom:3px">
<label target="txtEmailEdit" text="Email" class="NormalBold" width="100px" />
<textbox id="txtEmailEdit" datafield="Email" datatype="string" />
</div>

<div style="padding-bottom:3px">
<label target="txtWebEdit" text="Web Site" class="NormalBold" width="100px" />
<textbox id="txtWebEdit" datafield="Web" datatype="string" />
</div>
<div style="padding-bottom:3px">
<label target="txtPhoneEdit" text="Phone" class="NormalBold" width="100px" />
<textbox id="txtPhoneEdit" datafield="Phone" datatype="string" />
</div>

<div style="padding-bottom:3px">
<label target="txtCreatedByEdit" text="Created By" class="NormalBold" width="100px"/>
<textbox id="txtCreatedByEdit" datafield="CreatedBy" datatype="string" readonly="true" />
</div>

<div style="padding-bottom:3px">
<label target="txtLastUpdatedByEdit" text="Last Updated By" class="NormalBold" width="100px"/>
<textbox id="txtLastUpdatedByEdit" datafield="LastUpdatedBy" datatype="string" readonly="true" />
</div>

<div style="padding-bottom:3px">
<updatebutton text="Update"/>&nbsp;&nbsp;<cancelbutton text="Cancel"/>
</div>

<textbox id="txtHavenID" datafield="HavenID" datatype="int32" visible="false" />
</editForm>

Using the above example you should be able to build all sorts of Google maps solutions in no time at all with XMod Pro.

I’m looking forward to building a jQuery version and demonstrating some of the other features of Google maps you can use to enhance your XMod Pro solutions.

thanks for reading

Gus

Comments & Ratings

    (Ratings: 1   Avg: 2.00)
Rate It!
Share It!