This example is stored on a different site -- you can access it here https://sites.google.com/site/behaviorcemetery/
The table of information and map require a .css file and a .xml data file. The HTML and JavaScript for a server are given for the table of information -- it is converted to a Google gadget for display on the site by adding the xml information, rearranging the html and JavaScript and replacing the Ajax functions with gadget Ajax functions. Only the Google gadget code for the map is shown here. It can be converted to a server version following the outline of the HTML and JavaScript for the table.
HTML and JavaScript for the table of information Google Gadget xml for the map
HTML and JavaScript for a server.
<html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<title>Behavior Cemetery</title>
<script type="text/javascript">
function initialize () {
makeRequest("Behavior Cemetery.xml");
}
var xhr = false;
// issue AJAX request
function makeRequest(url) {
if (window.XMLHttpRequest) { xhr = new XMLHttpRequest(); }
else if (window.ActiveXObject) {xhr = new ActiveXObject("Microsoft.XMLHTTP");}
if (xhr) {
xhr.onreadystatechange = response;
xhr.open("GET", url, true);
xhr.send(null);
}
else document.write("ERROR - could not create XMLHttpRequest");
}
// process AJAX request when ready, expecting an XML document
function response() {
var xmldoc = '';
if (xhr.readyState == 4) {
// Run on server (200) or local machine (0) on Firefox, not Chrome
if (xhr.status == 200 || xhr.status == 0) {xmldoc = xhr.responseXML; dispXML(xmldoc); }
else document.write("ERROR - " + xhr.status);
}
}
function GraveId (id, name, firstName, lastName, latlng, born, died, epitaph, comments, image) {
this.id = id;
this.name = name;
this.firstName = firstName;
this.lastName = lastName;
this.latlng = latlng;
this.born = born;
this.died = died;
this.epitaph = epitaph;
this.comments = comments;
this.image = "http://sites.google.com/site/behaviorcemetery/images/" + image.replace(/[, ]/gi,"");
}
function dispXML(xmldoc) {
var info = "";
graveIds = new Array();
XMLmarkers = xmldoc.documentElement.getElementsByTagName("marker");
for (var i = 0; i < XMLmarkers.length; i++) {
graveIds[i] = new GraveId(XMLmarkers[i].getAttribute("id"), XMLmarkers[i].getAttribute("name"),
XMLmarkers[i].getAttribute("first"), XMLmarkers[i].getAttribute("last"), 0,
XMLmarkers[i].getAttribute("born"),XMLmarkers[i].getAttribute("died"),
XMLmarkers[i].getAttribute("epitaph"), XMLmarkers[i].getAttribute("comments"),XMLmarkers[i].getAttribute("image"));
if (graveIds[i].epitaph==null) graveIds[i].epitaph=" ";
if (graveIds[i].comments==null) graveIds[i].comments=" ";
}
graveIds.sort(sortNamesHandler);
fields=["Name (click for picture)","Born","Died","Epitaph","Comments"];
info = "<table border='1'>\n<tr>";
for (i=0; i<fields.length; i++)
info += "<th>"+fields[i]+"</th>";
info += "\n</tr>\n";
for (i=0;i<graveIds.length;i++) {
info += "<tr><td><a href='"+graveIds[i].image+"' >"+graveIds[i].name+"</td><td>"+
graveIds[i].born+"</td><td>"+graveIds[i].died+"</td><td>"+graveIds[i].epitaph+
"</td><td>"+graveIds[i].comments+"</td></tr>\n";
}
info += "</table>";
document.getElementById("table").innerHTML=info;
}
function sortNamesHandler(thisObject, thatObject) {
if (thisObject.lastName == thatObject.lastName) {
if (thisObject.firstName > thatObject.firstName) return 1;
else if (thisObject.firstName < thatObject.firstName) return -1;
else return 0;
}
if (thisObject.lastName > thatObject.lastName) return 1;
else if (thisObject.lastName< thatObject.lastName) return -1;
else return 0;
}
function displayList(graveIds) {
line="";
for(var i=0; i < graveIds.length; i++)
line+="id="+graveIds[i].id+" Name="+graveIds[i].name+" latlng="+graveIds[i].latlng+
" born="+graveIds[i].born+" died="+graveIds[i].died+" epitaph="+graveIds[i].epitaph+" comments="+graveIds[i].comments+
" image="+graveIds[i].image+"\n";
alert(line);
}
</script>
</head>
<body onload="initialize()">
<div style="background-color:#AAAAAA;">
<div id="header" style="text-align: center;">
<h1>Behavior Cemetery Sapelo Island, Georgia</h1>
</div>
<div id="table" style="background-color:#FFFFFF;"></div>
</div>
</body>
</html>
Google Gadget xml
The functions makeRequest and response are replaced with the Google Gadgets AJAX interface.
<?xml version="1.0" encoding="UTF-8" ?>
<Module>
<ModulePrefs title="Behavior Cemetery Map" height="300"
description="Behavior Cemetery Map"
author="Stephanie Smullen" author_email="stephanie.smullen@gmail.com">
<Require feature="sharedmap"/>
</ModulePrefs>
<Content type="html">
<![CDATA[
<div id="sidebar" style="width: 20%; height: 100%; float: right; background-color:#FFFFFF; background-repeat: no-repeat">
<img src="http://sites.google.com/site/behaviorcemetery/images/BehaviorSign.jpg" style="width: 126px; height: 95px; margin-left: 5pt" /><br/><br/>
<span style="font-size:12pt; font-weight:bold; margin-left: 5pt">Last name</span><br/>
<input type="text" id="nameInput" size="10" style="font-size:12pt; margin-left: 2pt"/>
<input type="button" onclick="searchName()" value="Search"/><br/><br/>
<div id="searchResults"></div>
<span style="font-size:12pt; font-weight:bold; margin-left: 5pt">Graves by last name:</span>
<ul id='tree' class='treeview' style='margin-left: 0pt'></ul>
</div>
<div id="header" style="width: 80%; height: 6%; background-color:#aaaaaa;text-align:center">
<h1>Behavior Cemetery Sapelo Island, Georgia</h1>
</div>
<div id="map_canvas" style="width: 80%; height: 93%; float: left;"></div>
<link rel="stylesheet" type="text/css" href="http://sites.google.com/site/behaviorcemetery/css/simpletree.css" />
<style type="text/css">div.gmnoprint div img { display: none;} </style>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript"">
// Dynamic Drive -- http://www.dynamicdrive.com/dynamicindex1/navigate1.htm
var persisteduls=new Object()
var ddtreemenu=new Object()
ddtreemenu.closefolder="http://sites.google.com/site/behaviorcemetery/images/closed.png"; //set image path to "closed" folder image
ddtreemenu.openfolder="http://sites.google.com/site/behaviorcemetery/images/open.png"; //set image path to "open" folder image
//////////No need to edit beyond here///////////////////////////
ddtreemenu.createTree=function(treeid, enablepersist, persistdays){
var ultags=document.getElementById(treeid).getElementsByTagName("ul")
if (typeof persisteduls[treeid]=="undefined")
persisteduls[treeid]=(enablepersist==true && ddtreemenu.getCookie(treeid)!="")? ddtreemenu.getCookie(treeid).split(",") : ""
for (var i=0; i<ultags.length; i++)
ddtreemenu.buildSubTree(treeid, ultags[i], i)
if (enablepersist==true){ //if enable persist feature
var durationdays=(typeof persistdays=="undefined")? 1 : parseInt(persistdays)
ddtreemenu.dotask(window, function(){ddtreemenu.rememberstate(treeid, durationdays)}, "unload") //save opened UL indexes on body unload
}
}
ddtreemenu.buildSubTree=function(treeid, ulelement, index){
ulelement.parentNode.className="submenu"
if (typeof persisteduls[treeid]=="object"){ //if cookie exists (persisteduls[treeid] is an array versus "" string)
if (ddtreemenu.searcharray(persisteduls[treeid], index)){
ulelement.setAttribute("rel", "open")
ulelement.style.display="block"
ulelement.parentNode.style.backgroundImage="url("+ddtreemenu.openfolder+")"
}
else
ulelement.setAttribute("rel", "closed")
} //end cookie persist code
else if (ulelement.getAttribute("rel")==null || ulelement.getAttribute("rel")==false) //if no cookie and UL has NO rel attribute explicted added by user
ulelement.setAttribute("rel", "closed")
else if (ulelement.getAttribute("rel")=="open") //else if no cookie and this UL has an explicit rel value of "open"
ddtreemenu.expandSubTree(treeid, ulelement) //expand this UL plus all parent ULs (so the most inner UL is revealed!)
ulelement.parentNode.onclick=function(e){
var submenu=this.getElementsByTagName("ul")[0]
if (submenu.getAttribute("rel")=="closed"){
submenu.style.display="block"
submenu.setAttribute("rel", "open")
ulelement.parentNode.style.backgroundImage="url("+ddtreemenu.openfolder+")"
}
else if (submenu.getAttribute("rel")=="open"){
submenu.style.display="none"
submenu.setAttribute("rel", "closed")
ulelement.parentNode.style.backgroundImage="url("+ddtreemenu.closefolder+")"
}
ddtreemenu.preventpropagate(e)
}
ulelement.onclick=function(e){
ddtreemenu.preventpropagate(e)
}
}
ddtreemenu.expandSubTree=function(treeid, ulelement){ //expand a UL element and any of its parent ULs
var rootnode=document.getElementById(treeid)
var currentnode=ulelement
currentnode.style.display="block"
currentnode.parentNode.style.backgroundImage="url("+ddtreemenu.openfolder+")"
while (currentnode!=rootnode){
if (currentnode.tagName=="UL"){ //if parent node is a UL, expand it too
currentnode.style.display="block"
currentnode.setAttribute("rel", "open") //indicate it's open
currentnode.parentNode.style.backgroundImage="url("+ddtreemenu.openfolder+")"
}
currentnode=currentnode.parentNode
}
}
ddtreemenu.flatten=function(treeid, action){ //expand or contract all UL elements
var ultags=document.getElementById(treeid).getElementsByTagName("ul")
for (var i=0; i<ultags.length; i++){
ultags[i].style.display=(action=="expand")? "block" : "none"
var relvalue=(action=="expand")? "open" : "closed"
ultags[i].setAttribute("rel", relvalue)
ultags[i].parentNode.style.backgroundImage=(action=="expand")? "url("+ddtreemenu.openfolder+")" : "url("+ddtreemenu.closefolder+")"
}
}
ddtreemenu.rememberstate=function(treeid, durationdays){ //store index of opened ULs relative to other ULs in Tree into cookie
var ultags=document.getElementById(treeid).getElementsByTagName("ul")
var openuls=new Array()
for (var i=0; i<ultags.length; i++){
if (ultags[i].getAttribute("rel")=="open")
openuls[openuls.length]=i //save the index of the opened UL (relative to the entire list of ULs) as an array element
}
if (openuls.length==0) //if there are no opened ULs to save/persist
openuls[0]="none open" //set array value to string to simply indicate all ULs should persist with state being closed
ddtreemenu.setCookie(treeid, openuls.join(","), durationdays) //populate cookie with value treeid=1,2,3 etc (where 1,2... are the indexes of the opened ULs)
}
////A few utility functions below//////////////////////
ddtreemenu.getCookie=function(Name){ //get cookie value
var re=new RegExp(Name+"=[^;]+", "i"); //construct RE to search for target name/value pair
if (document.cookie.match(re)) //if cookie found
return document.cookie.match(re)[0].split("=")[1] //return its value
return ""
}
ddtreemenu.setCookie=function(name, value, days){ //set cookei value
var expireDate = new Date()
//set "expstring" to either future or past date, to set or delete cookie, respectively
var expstring=expireDate.setDate(expireDate.getDate()+parseInt(days))
document.cookie = name+"="+value+"; expires="+expireDate.toGMTString()+"; path=/";
}
ddtreemenu.searcharray=function(thearray, value){ //searches an array for the entered value. If found, delete value from array
var isfound=false
for (var i=0; i<thearray.length; i++){
if (thearray[i]==value){
isfound=true
thearray.shift() //delete this element from array for efficiency sake
break
}
}
return isfound
}
ddtreemenu.preventpropagate=function(e){ //prevent action from bubbling upwards
if (typeof e!="undefined")
e.stopPropagation()
else
event.cancelBubble=true
}
ddtreemenu.dotask=function(target, functionref, tasktype){ //assign a function to execute to an event handler (ie: onunload)
var tasktype=(window.addEventListener)? tasktype : "on"+tasktype
if (target.addEventListener)
target.addEventListener(tasktype, functionref, false)
else if (target.attachEvent)
target.attachEvent(tasktype, functionref)
}
</script>
<script type="text/javascript">
var infowindow;
function initialize() {
var myOptions = {zoom: 19, center: new google.maps.LatLng(31.4285,-81.281097), mapTypeId: google.maps.MapTypeId.SATELLITE };
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
google.maps.event.addListener(map, 'click', function() {
if (infoWindowLast) infoWindowLast.close();
map.setCenter(new google.maps.LatLng(31.4285,-81.281097));
});
var cemetaryCoordinates = [
new google.maps.LatLng(31.428043,-81.279663), // outer NE fence corner
new google.maps.LatLng(31.428776,-81.280288), // inner NE fence corner
new google.maps.LatLng(31.42897,-81.280449), // angled fence post
new google.maps.LatLng(31.429034,-81.28054), // east entrance gate
new google.maps.LatLng(31.429053,-81.280568), // center of gate - "500N500E" grid marker
new google.maps.LatLng(31.429069,-81.280592), // west entrance gate
new google.maps.LatLng(31.42924,-81.280844), // NW fence corner
new google.maps.LatLng(31.428825,-81.281097), // fence1
new google.maps.LatLng(31.428294,-81.281442), // fence2
new google.maps.LatLng(31.42784,-81.281733), // SW fence corner
new google.maps.LatLng(31.427679,-81.281196), // fence
new google.maps.LatLng(31.427595,-81.280899), // fence4 -- SE corner
new google.maps.LatLng(31.427365,-81.280108), // outer SE fence corner
new google.maps.LatLng(31.428043,-81.279663) // outer NE fence corner return
];
cemetaryPolyline = new google.maps.Polyline({
path: cemetaryCoordinates, strokeColor: "#FF0000", strokeOpacity: 0.65,
strokeWeight: 4, zIndex: 1});
cemetaryPolyline.setMap(map);
makeRequest("http://sites.google.com/site/behaviorcemetery/images/BehaviorCemetery.xml");
}
// issue AJAX request
function makeRequest (url) {
var params = {};
params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.DOM;
gadgets.io.makeRequest(url, response, params);
}
function response (obj) {
dispXML(obj.data);
}
function GraveId (id, name, firstName, lastName, latlng, born, died, epitaph, comments, image) {
this.id = id;
this.name = name;
this.firstName = firstName;
this.lastName = lastName;
this.latlng = latlng;
this.born = born;
this.died = died;
this.epitaph = epitaph;
this.comments = comments;
this.image = "http://sites.google.com/site/behaviorcemetery/images/" + image.replace(/[, ]/gi,"");
}
var markers= [];
function dispXML(xmldoc) {
graveIds = new Array();
XMLmarkers = xmldoc.documentElement.getElementsByTagName("marker");
for (var i = 0; i < XMLmarkers.length; i++) {
id = XMLmarkers[i].getAttribute("id");
if (XMLmarkers[i].getAttribute("joint")=="B") id=5+id;
graveIds[i] = new GraveId(id,
XMLmarkers[i].getAttribute("name"),
XMLmarkers[i].getAttribute("first"), XMLmarkers[i].getAttribute("last"),
new google.maps.LatLng(parseFloat(XMLmarkers[i].getAttribute("lat")),parseFloat(XMLmarkers[i].getAttribute("lng"))),
XMLmarkers[i].getAttribute("born"),XMLmarkers[i].getAttribute("died"),
XMLmarkers[i].getAttribute("epitaph"), XMLmarkers[i].getAttribute("comments"),XMLmarkers[i].getAttribute("image"));
if (graveIds[i].epitaph==null) graveIds[i].epitaph=" ";
if (graveIds[i].comments==null) graveIds[i].comments=" ";
markers[graveIds[i].id]=createMarker(graveIds[i].name,graveIds[i].latlng,graveIds[i].born,graveIds[i].died,
graveIds[i].epitaph,graveIds[i].comments,graveIds[i].image);
}
graveIds.sort(sortNamesHandler);
//displayList(graveIds);
createList(graveIds,"tree");
return graveIds;
}
function displayList(graveIds) {
line="";
for(var i=0; i < graveIds.length; i++)
line+="id="+graveIds[i].id+" Name="+graveIds[i].name+" latlng="+graveIds[i].latlng+
" born="+graveIds[i].born+" died="+graveIds[i].died+" epitaph="+graveIds[i].epitaph+" comments="+graveIds[i].comments+
" image="+graveIds[i].image+"\n";
alert(line);
}
function sortNamesHandler(thisObject, thatObject) {
if (thisObject.lastName == thatObject.lastName) {
if (thisObject.firstName > thatObject.firstName) return 1;
else if (thisObject.firstName < thatObject.firstName) return -1;
else return 0;
}
if (thisObject.lastName > thatObject.lastName) return 1;
else if (thisObject.lastName< thatObject.lastName) return -1;
else return 0;
}
// Create the dynamic tree display
function createList(graveIds,spotName) {
var alpha = ["A-B","C-E","F-G","H-I","J-L","M-R","S-U","W-Z"];
if (navigator.appName != "Microsoft Internet Explorer")
document.getElementById("tree").style.marginLeft='-20pt';
var info="";
var set = 0;
info += "<li style='background-color: #AAAAAA; padding-left: 20'>"+alpha[set]+"\n<ul>\n";
for (j=0;j<graveIds.length;j++) {
if (graveIds[j].lastName.indexOf("unidentified")<0) {
if (graveIds[j].lastName.charAt(0).toUpperCase() > alpha[set].charAt(2) ) {
set++;
while (graveIds[j].lastName.charAt(0).toUpperCase() > alpha[set].charAt(2) )
info += "</ul>\n</li>\n<li style='padding-left: 20 '>"+alpha[set++]+"\n<ul>\n";
info += "</ul>\n</li>\n<li style='background-color: #AAAAAA; padding-left: 20 '>"+alpha[set]+"\n<ul>\n";
}
a = "<a onclick='openName("+graveIds[j].id+");'>";
info += "<li style='background-color:#FFFFFF; padding-left: 0 '>"+a+graveIds[j].name+"</li>\n";
}
}
for (i=set+1; i<alpha.length; i++) info += "</ul>\n</li>\n<li style='font-size: 8pt;background-color:#AAAAAA; padding-left: 20 '>"+alpha[i]+"\n<ul>\n";
info+="</ul>\n</li>\n</ul>";
var tab = document.getElementById(spotName);
tab.innerHTML = info;
ddtreemenu.createTree(spotName, false);
ddtreemenu.flatten(spotName, 'contract');
}
function searchName() {
last = document.getElementById("nameInput").value;
info ='<table border="1"><tr>';
table=0;
for (i=0;i<graveIds.length;i++)
if (graveIds[i].lastName.toUpperCase() == last.toUpperCase()) {
info+="<td>"+"<a onclick='openName("+graveIds[i].id+");'>"+ graveIds[i].name+"</td>";
if ((table++)%2==1) info+="</tr>\n<tr>";
}
info+="</table>";
document.getElementById("searchResults").innerHTML=info;
document.getElementById("nameInput").value="";
}
var redicon ="http://chart.apis.google.com/chart?cht=it&chs=10&chco=ff0000ff&chx=000000,10&chf=bg,s,00000000";
var blueicon = "http://chart.apis.google.com/chart?cht=it&chs=10&chco=0000ffff&chx=000000,10&chf=bg,s,00000000";
var infoWindowLast = null;
function openInfoWindow (map, infoWindow, marker) {
return function() {
// Close the last selected marker before opening this one.
if (infoWindowLast) {infoWindowLast.close(); }
infoWindow.open(map, marker);
infoWindowLast = infoWindow;
};
}
function openName (which) {
scrollTo(0,0);
google.maps.event.trigger(markers[which], "click");
}
function createMarker(name, latlng, born, died, epitaph, comments, image) {
// if no information (UID) create a blue marker
if (name == "unidentified") {
marker = new google.maps.Marker({position: latlng, map: map, title: name,icon: blueicon });
infowindow = new google.maps.InfoWindow({
content: '<div><p><b>Unidentifiable</b><br /><a href="'+image+
'" alt="larger image"><img src="'+image+
' " style="width: 126px; height: 95px" /></a><br />'+
'<span style="font-size: 8pt">*Click on image for a larger view</span><br/>'+
'<b>comments: </b>'+ comments +' </div>',
maxWidth: 200});
google.maps.event.addListener(marker, "click", openInfoWindow(map, infowindow, marker));
}
else {
marker = new google.maps.Marker({position: latlng, map: map, title: name,icon: redicon, flat:true});
infowindow = new google.maps.InfoWindow({content:
'<div>'+
'<p><b>'+name+'</b><br />'+
'<a href="'+image+'" alt="larger image">'+
'<img src="'+image+' " style="width: 126px; height: 95px" /></a><br />'+
'<span style="font-size: 8pt">*Click on image for a larger view</span><br/>'+
'<b>born: </b>'+ born +' <br />'+
'<b>died: </b>'+ died +' <br />'+
'<b>epitaph: </b>'+ epitaph +' <br />'+
'<b>comments: </b>'+ comments +' <br />'+
'</div>',
maxWidth: 200});
google.maps.event.addListener(marker, "click", openInfoWindow(map, infowindow, marker));
}
return marker;
}
gadgets.util.registerOnLoadHandler(initialize);
</script>
]]>
</Content>
</Module>