<?xml version="1.0" encoding="UTF-8"?>
<Module> 
<ModulePrefs title="Spreadsheets Geocoder"
             description="Geocoding is the process of converting an address to a coordinate pair, and its necessary to plot data on a map. This gadget helps you geocode addresses from your spreadsheet, and gives you an output thats easy to copy-and-paste back into your sheet."
             author="Pamela Fox"
             author_affiliation="Google Inc."
             author_email="pamela.fox+coolgadget@gmail.com"
             screenshot="http://pamela.fox.googlepages.com/screenshot_spreadsheetsgeocodergadge.jpg"
             thumbnail="http://pamela.fox.googlepages.com/thumbnail_spreadsheetsgeocodergadget.jpg" 
              width="600" height="600"> 
<Require feature="idi"/>
<Require feature="locked-domain" />
<Require feature="grid"/>
</ModulePrefs>
<UserPref name="_table_query_url" display_name="Data source url" 
          required="true"/>
<UserPref name="_table_query_refresh_interval" 
          display_name="Data refresh interval (minutes)" 
          default_value="0" datatype="enum" required="false">
<EnumValue value="0" display_value="Do not refresh"/>
<EnumValue value="60" display_value="1"/>
<EnumValue value="300" display_value="5"/>
<EnumValue value="1800" display_value="30"/>
</UserPref>
<Content type="html"><![CDATA[
<style type="text/css">
table {
  border: 0px;
  border-spacing:0;
  margin:0px;
}
td {
  border:0px;
  padding:0px;
  margin:0px;
  height:40px;
  text-align:center;
  font-size:11pt;
}
body {
  font-family:Arial, sans serif;
  font-size:11pt;
}
</style>

<div style="margin-left: 10px;">

<div style="display:none;" id="configDIV">
Address column: <input type="text" value="B" id="addressColumn"/>
Name column: <input type="text" value="A" id="nameColumn"/>
<p>
<input type="button" onclick="loadWords();" value="Load Points"/>
</p>
</div>

<div id="map" style="width:65%; height:400px; border:2px solid black; float:left; clear:both;"></div>

<div id="infoDIV" style="overflow-y:auto; overflow-x: hidden; padding-left:0px; height:400px; float:left; border:2px solid black; width:25%">
Click on a marker on the map to see the data for a particular state. The numbers on the markers indicate the number of rows found for that state.
</div>

</div>
<script src="http://imagine-it.org/google/states.js"></script>
<script src="http://gmaps-utility-library-dev.googlecode.com/svn/trunk/mapiconmaker/src/mapiconmaker.js"></script>
<script src="http://www.google.com/jsapi?key=ABQIAAAA-O3c-Om9OcvXMOJXreXHAxTZqGWfQErE9pT-IucjscazSdFnjBTc_GPovcgWfia3_ru3nhdxaquODA" type="text/javascript"></script>
<script language="JavaScript">
/**
 * Load the APIs and run sendQuery when the load is complete
 */
var gadgetHelper = null;
var prefs = null;
var map = null;
var addresses = [];
var entries;

var columns = new Array();
var baseIcon = null;
var bounds = null;
var unfoundMarkers = new Array();
var markerOverlays = new Array();
var loaded = false;
var poly = null;
var markerSelected = null;
var polySelected = null;
var color = "#4169FF";
var colorSelected = "#0000FF";

_IG_RegisterOnloadHandler(loadVisualizationAPI);
      
function loadVisualizationAPI() { 
  google.load("visualization", "1");
  google.load("maps", "2.x");
  google.setOnLoadCallback(sendQuery);
}

/**
 * Create a query (shaped by the Gadget's user preferences), then 
 * send it to the spreadsheet data source. Also give the name of a 
 * function ("handleQueryResponse") to run once the spreadsheet data 
 * is retrieved:
 */
function sendQuery() {
  prefs = new _IG_Prefs(); // User preferences 
  gadgetHelper = new google.visualization.GadgetHelper(); 
  var query = gadgetHelper.createQueryFromPrefs(prefs);
  query.send(handleQueryResponse);
  //getJs();
} 

function getJs() {
  var script = document.createElement("script");
  script.src = "http://imagine-it.org/google/slideshowcontrol.js";
  script.onload = loadMap;
  document.body.appendChild(script);
}

/**
 * The core logic. Process the spreadsheet data however you want. 
 * In this case, we create HTML to be presented back to the user. 
 * We'll use inline comments to provide a step-by-step description 
 * of what we're doing:
 */
function handleQueryResponse(response) {
  if (!gadgetHelper.validateResponse(response)) {
    return;     // Default error handling was done, just leave. 
  }
  data = response.getDataTable();
  loadMap();
  loadWords();
}


/**
 * Loads the map into div with 'map' id.
 * Adds controls, sets initial center.
 * Initializes geocoder.
 */
function loadMap() {
  map = new GMap2(document.getElementById("map"));
  map.addControl(new GSmallMapControl());
  map.addControl(new GMapTypeControl());
  map.setCenter(new GLatLng(37.0625,-95.677068), 3);
  //map.addControl(new SlideshowControl({interval: 1000}), new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(7, 30)));  
  GEvent.addListener(map, "zoomend", function() {
    clearPolys();
  });
  baseIcon = new GIcon();
  baseIcon.shadow = "http://www.google.com/mapfiles/shadow50.png";
  baseIcon.iconSize = new GSize(20, 34);
  baseIcon.shadowSize = new GSize(37, 34);
  baseIcon.iconAnchor = new GPoint(9, 34);
  baseIcon.infoWindowAnchor = new GPoint(9, 2);
  baseIcon.infoShadowAnchor = new GPoint(18, 25);
}

function loadWords() {
  unfoundMarkers.length = 0;
  markerOverlays.length = 0;
  map.clearOverlays();

  var addressColumn = document.getElementById("addressColumn").value.charCodeAt(0) - 65;
  var nameColumn = document.getElementById("nameColumn").value.charCodeAt(0) - 65;

  var dataSimple = [];
  for (var row = 0; row < data.getNumberOfRows(); row++) {
    var address = data.getFormattedValue(row, addressColumn).toLowerCase();
    var name = data.getFormattedValue(row, nameColumn);
    dataSimple.push({address: address, name: name});
  }
  
  for (stateCode in states) {
    var regex = new RegExp("(\\s|,|^)(" + stateCode + ")(\\s|,|$)");
    states[stateCode].matches = [];
    for (var row = 0; row < dataSimple.length; row++) {
      if (regex.test(dataSimple[row].address)) {
        states[stateCode].matches.push(dataSimple[row]);
      }
    }
  }

  // find max
  var maxSize = 50;
  var maxCount = 0;
  for (stateCode in states) {
    maxCount = Math.max(maxCount, states[stateCode].matches.length);
  }
  var multiplier = maxSize/(maxCount+20);
  // create markers
  for (stateCode in states) {
    var state = states[stateCode];
    if (state.matches.length == 0) continue;
    var latlng = new GLatLng(state.centroid[1], state.centroid[0]);
    var latlngs = [];
    for (var i = 0; i < state.area.length; i++) {
      var latlngt = state.area[i];
      latlngs.push(new GLatLng(latlngt[0], latlngt[1]));
    }
    var title = state.name;
    var size = Math.round((state.matches.length+20) * multiplier);
    var label = state.matches.length + "";
    var html = "<div style='width:100%; color: #FFFFFF; text-align:center; font-size: 18px; background-color:" + colorSelected + ";'>" + state.name + "</div><br/>" + createMatchesHtml(state.matches);
    var marker = createMarkerForState(latlng, latlngs, title, html, size, label);
    map.addOverlay(marker);
  }
}

function createMatchesHtml(matches) {
  var html = [];
  for (var i = 0; i < matches.length; i++) {
    html.push("<div><b>" + matches[i].name + "</b>" + "<br/>" + matches[i].address + "</div>");
  }
  return html.join("");
}

function createMarkerForState(latlng, latlngs, title, html, size, label) {
  var iconNormal = MapIconMaker.createFlatIcon({width: size, height: size, label: label, labelColor: "#ffffff", primaryColor: color});
  var iconSelected = MapIconMaker.createFlatIcon({width: size, height: size, label: label, labelColor: "#ffffff", primaryColor: colorSelected});
  
  var marker = new GMarker(latlng, {icon: iconNormal, title: title});
  marker.iconNormal = iconNormal;
  marker.iconSelected = iconSelected;

  GEvent.addListener(marker, "click", function() {
    if (polySelected) { map.removeOverlay(polySelected); }
    if (markerSelected) { markerSelected.setImage(markerSelected.iconNormal.image); } 
    polySelected = new GPolygon(latlngs, colorSelected, 1, 1, colorSelected, .2);
    map.addOverlay(polySelected);
    document.getElementById("infoDIV").innerHTML = html;
    console.log(iconSelected);
    marker.setImage(iconSelected.image);
    markerSelected = marker;
  });
  GEvent.addListener(marker, "mouseover", function() {
    if (poly) { map.removeOverlay(poly); }
    poly = new GPolygon(latlngs, color, 1, 1, color, .2);
    map.addOverlay(poly);
  });
  GEvent.addListener(marker, "mouseout", function() {
    if (poly) { map.removeOverlay(poly); }
  });
  return marker;
}


function log(thing) {
  if (window["console"]) {
    console.log(thing);
   }
}
</script>

  ]]>
  </Content>
</Module> 

