Source code of a graphical tool for drawing and computing distances over Google maps.
Run Tool | index.html | main.css | formatters.js | geoCircle.js | geoCode.js | geo.js | index.js | mapControls.js | tableManager.js | util.js | wayPoint.js | wayPointsManager.js
// Copyright 2006-2008 (c) Paul Demers <paul@acscdg.com>
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA., or visit one
// of the links here:
// http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
// http://www.acscdg.com/LICENSE.txt
//////////////////////////////////////////////////////////////////
// This application implements drawing tools on top of Google maps
// using JavaScript.
// Web site with this code running: http://www.acscdg.com/
//
//////
// Global variables:
var _fullyLoaded = false; // This is needed because IE calls the onResize
// call back many times during initialization.
// Application state variables:
var _circleMode = false;
var _wayPointsListManager = null; // The current way point List.
var _currentCircle = null;
var _tempWayPoint = null;
// Filled in at load time:
var _changeUnitsBoxElement;
var _currentDistanceUnits = NAUTICAL_MILES_UNITS;
// Element cache:
var _mapElement; // The html div element that holds the map,
// used during window resize.
var _tableElement; // The html div element that holds the points table,
// used during window resize.
var _innerElement; // The html div element that wraps the points table and the map,
// used during window resize.
var _map; // Points to the map object, needs to be global for resize.
// Objects created once and shared:
var _wayPointIcon; // The blueX icon at each way point and the center of the circle.
var _adsManager; // Google maps ad manager.
var _optsNotClickable = {clickable:false}; // Set all lines as not clickable.
// Otherwise, the redraw on mouse move doesn't work.
// The map control objects.
var startControl = null;
var wayPointsInProgressControl = null;
var circleInProgressControl = null;
////
//
//
///////////////////////////////////////////////////////
//
//// Called when the "start course" button is pushed.
function startCourse(map)
{
removeTempWayPoint(map);
map.removeControl(startControl);
map.addControl(wayPointsInProgressControl);
_wayPointsListManager = _tableManager.addWayPointList();
}
//
//// called when either of the "end course" buttons are pushed.
function endCourse(map)
{
removeTempWayPoint(map);
map.removeControl(wayPointsInProgressControl);
map.addControl(startControl);
_wayPointsListManager = null;
}
//
//// Called when the "end course at last point" button is pushed.
function endCourseAtLast(map)
{
endCourse(map);
}
//
//// Called when the "end course at first point" button is pushed.
function endCourseAtFirst(map)
{
if (_wayPointsListManager == null)
return;
var firstWayPoint = null;
if ((firstWayPoint = _wayPointsListManager.getFirstWayPoint()) != null)
{
var lastWayPoint = createWayPoint(map, firstWayPoint.point);
// No need to add another marker. Although it would be nice to change
// the label on the reused marker to 0, [last]
_wayPointsListManager.pushWayPoint(lastWayPoint); // make point permanent.
}
endCourse(map);
}
//
//// Called when the "remove last point" button is pushed.
function removeLastCoursePoint(map)
{
removeTempWayPoint(map);
if (_wayPointsListManager == null)
return;
var lastWayPoint;
if ((lastWayPoint = _wayPointsListManager.removeLastWayPoint()) != null)
{
_tempWayPoint = lastWayPoint;
// Leave the courseLine, because it is now the temp course line.
map.removeOverlay(lastWayPoint.marker);
lastWayPoint.marker = null;
if (_wayPointsListManager.numberOfPoints() == 0)
{
// If no points are left, remove the temp way point, too.
removeTempWayPoint(map);
}
else
{
; // there are still points left.
}
}
}
//
//// Make the temporary way point permanent.
function chooseWayPoint(map, marker, point)
{
// Redraw everything in case the mouse moved between the last move event and the button event.
drawTempWayPoint(map, point);
var wayPoint = _tempWayPoint;
_tempWayPoint = null;
// Leave a marker behind.
var marker = new GMarker(point, {title: wayPoint.name, icon: _wayPointIcon });
map.addOverlay(marker);
wayPoint.marker = marker;
_wayPointsListManager.pushWayPoint(wayPoint); // make point permenant.
}
//
//// Called when mouse moves and also after mouse down, via its handler.
function createWayPoint(map, point)
{
if (_wayPointsListManager == null)
return null;
var lastWayPoint = _wayPointsListManager.getLastWayPoint(); // if lastWayPoint is null,
// then this is the first point.
var pointNumber = _wayPointsListManager.numberOfPoints();
var wayPoint = new WayPoint(map, _wayPointsListManager.courseNumber,
pointNumber, point, lastWayPoint, _currentDistanceUnits);
_wayPointsListManager.addWayPointTableElement(wayPoint);
return(wayPoint);
}
//
//// Removes the overlays, objects, and elements of the temp way point.
function removeTempWayPoint(map)
{
if (_tempWayPoint != null)
{
if (_tempWayPoint.courseLine != null)
map.removeOverlay(_tempWayPoint.courseLine);
_wayPointsListManager.removeWayPointTableElement(_tempWayPoint);
_tempWayPoint = null;
}
}
//
//// Called when the mouse moves.
function drawTempWayPoint(map, endPoint)
{
if (_tempWayPoint != null)
_tempWayPoint.update(map, endPoint, _currentDistanceUnits);
else
_tempWayPoint = createWayPoint(map, endPoint);
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//// Called from choosePoint
function startCircle(map, centerPoint)
{
_currentCircle = _tableManager.addCircle(map, centerPoint, _currentDistanceUnits);
}
//
//// Called from choosePoint
function finishCircle(map, edgePoint)
{
drawTempCircle(map, edgePoint, true);
_currentCircle = null;
leaveCircleMode(map);
}
//
//// Called when the "remove last circle" button is pushed.
function eraseLastCircle(map)
{
_currentCircle = null;
var lastCircle = _tableManager.removeLastCircle();
if (lastCircle != null)
lastCircle.removeOverlays(map);
}
//
//// Called when the mouse button is clicked.
function chooseCirclePoint(map, marker, point)
{
if (_currentCircle == null)
startCircle(map, point); // If this is the first point of a circle,
// then it is the center.
else
finishCircle(map, point); // If it is the second point, then it is a point
// on the edge, and finishes the circle
}
//
//// Called when the mouse moves.
function drawTempCircle(map, edgePoint, finalP)
{
if (_currentCircle != null)
_currentCircle.update(map, edgePoint, finalP, _currentDistanceUnits);
}
//////////////////////////////////////////////////////////////////////////////////
//
//
//// Called when the distance units pull down box is changed.
function changeUnits()
{
_currentDistanceUnits = _changeUnitsBoxElement[_changeUnitsBoxElement.selectedIndex].value;
_tableManager.redrawPointsTable(_currentDistanceUnits);
if (_tempWayPoint != null)
{
_tempWayPoint.updateElement(_currentDistanceUnits);
}
}
//
//// Loads the way point icon from a file into memory.
//// only needs to be called once.
function createWayPointIcon()
{
_wayPointIcon = new GIcon();
_wayPointIcon.image = "blueX40.png";
_wayPointIcon.iconSize = new GSize(40, 40);
_wayPointIcon.iconAnchor = new GPoint(20, 20);
_wayPointIcon.infoWindowAnchor = new GPoint(24, 16);
}
//
//// Called when the "Clear" button is pushed.
function clearAll(map)
{
map.clearOverlays();
_tableManager.clearTable();
_currentCircle = null;
_wayPointsListManager = null;
}
//
////
function enterCircleMode(map)
{
map.removeControl(startControl);
map.addControl(circleInProgressControl);
removeTempWayPoint(map);
_wayPointsListManager = null;
_circleMode = true;
}
//
////
function leaveCircleMode(map)
{
map.removeControl(circleInProgressControl);
map.addControl(startControl);
if (_currentCircle != null)
_currentCircle.removeOverlays();
_currentCircle = null;
_circleMode = false;
}
//
//// Called when the mouse button is clicked.
function choosePoint(map, marker, point)
{
if (marker && marker instanceof GMarker)
{
// Get the coords of the marker if one was clicked.
point = marker.getLatLng();
}
if (point == null) // if still null, this is a call on the polyline, not the map or a marker.
// remove this after Google improves the API.
return;
// TODO: It would be great to read back the name of the icon if it was a geo-coded location,
// to then set the name of the point or circle to the name of the location.
if (_circleMode)
chooseCirclePoint(map, marker, point);
else if (_wayPointsListManager != null)
chooseWayPoint(map, marker, point);
}
//
//// Called when the mouse moves.
function drawTempPoint(map, point)
{
if (_circleMode)
drawTempCircle(map, point, false);
else
drawTempWayPoint(map, point);
}
//////////////////////////////////////////////////////////////
//
////
function load()
{
var isCompatible = false;
if (GBrowserIsCompatible())
isCompatible = true;
if (!isCompatible)
{
window.location.replace("notCompatible.html");
return;
}
_tableManager = new TableManager(); // Singleton class.
_mapElement = document.getElementById("map");
_tableElement = document.getElementById("pointsTableDiv");
_innerElement = document.getElementById("inner");
// Called here to set the global variable from the html default.
_changeUnitsBoxElement = document.getElementById("changeUnitsBox");
changeUnits();
_map = new GMap2(_mapElement);
_map.setCenter(new GLatLng(41.3, -95.89), 3); // The center of North America and the Carabean Sea.
// Also a runway at OMA airport.
// Add the Google controls to the map:
_map.addControl(new GLargeMapControl());
_map.addControl(new GMapTypeControl());
// Create and add custom controls to the map:
startControl = new StartControl();
wayPointsInProgressControl = new WayPointsInProgressControl();
circleInProgressControl = new CircleInProgressControl();
// Set event listeners.
GEvent.addListener(_map, "click", function(marker, point) { choosePoint(_map, marker, point) } );
GEvent.addListener(_map, "mousemove", function(point) { drawTempPoint(_map, point) } );
// Start in non-drawing.
_map.addControl(startControl);
// Call one-time functions:
createWayPointIcon();
initGeoCoder();
adsManager = new GAdsManager(_map, "insert_your_google_publisher_id_here");
adsManager.enable();
_fullyLoaded = true;
resizeBody(); // Now that everything is set up, set the map size.
}