Source for file GoogleMap.php
Documentation is available at GoogleMap.php
* Project: GoogleMapAPI V3: a PHP library inteface to the Google Map API v3
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* This library 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
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* link http://www.phpinsider.com/php/code/GoogleMapAPI/
* copyright 2005 New Digital Group, Inc.
* author Monte Ohrt <monte at ohrt dot com>
* NOTE: This is a modified version of the original listed above. This version
* maintains all original GNU software licenses.
* @link http://code.google.com/p/php-google-map-api/
* @copyright 2010 Brad wedell
* @package GoogleMapAPI (version 3)
* To view the full CHANGELOG, visit
* http://code.google.com/p/php-google-map-api/wiki/ChangeLog3
For database caching, you will want to use this schema:
address varchar(255) NOT NULL default '',
* PHP Google Maps API class
* PEAR::DB DSN for geocode caching. example:
* current map id, set when you instantiate
* the GoogleMapAPI object.
* determines whether or not to display the map and associated JS on the page
* this is used if you just want to display a streetview with no map
* sidebar <div> used along with this map.
* Whether to use new V3 mobile functionality
* DEPRECATED: Google now has geocoding service.
* NOTE: Note even sure if this still works
* GoogleMapAPI used to use the Yahoo geocode lookup API.
* This is the application ID for YOUR application.
* This is set upon instantiating the GoogleMapAPI object.
* (http://developer.yahoo.net/faq/index.html#appid)
* use onLoad() to load the map javascript.
* if enabled, be sure to include on your webpage:
* <?=$mapobj->printOnLoad?> or manually create an onload function
* that calls the map's onload function using $this->printOnLoadFunction
* map center latitude (horizontal)
* calculated automatically as markers
* map center longitude (vertical)
* calculated automatically as markers
* enables map controls (zoom/move/center)
* determines the map control type
* small -> show move/center controls
* large -> show move/center/zoom controls
* enables map type controls (map/satellite/hybrid/terrain)
* determines unit system to use for directions, blank = default
* @var string (METRIC, IMPERIAL)
* sets default option for type controls(DEFAULT, HORIZONTAL_BAR, DROPDOWN_MENU)
* default map type google.maps.MapTypeId.(ROADMAP, SATELLITE, HYBRID, TERRAIN)
* enables scale map control
* class variable to control scrollwheel
* enables overview map control
* enables Google Adsense Adsmanager on page, not currently supported in beta
* Google Adsense Publisher ID
* Google Adsense Channel ID
* The Max number of Adsmanager ads to show on a map
* enables/disables local search on page
* enables local search ads on page NOTE: will only display ads if local_search == true, otherwise just use ad_manager and settings.
* enables/disables walking directions option
* enables/disables biking directions on directions
* enables/disables avoid highways on directions
* determines if avoid tollways is used in directions
* determines the default zoom level
* determines the map width
* determines the map height
* message that pops up when the browser is incompatible with Google Maps.
* set to empty string to disable.
var $browser_alert = 'Sorry, the Google Maps API is not compatible with this browser.';
* message that appears when javascript is disabled.
* set to empty string to disable.
var $js_alert = '<b>Javascript must be enabled in order to use Google Maps.</b>';
* determines if sidebar is enabled
* determines if to/from directions are included inside info window
* determines if map markers bring up an info window
* determines if info window appears with a click or mouseover
* @var string click/mouseover
* determines whether or not to use the MarkerClusterer plugin
* set default marker clusterer *webserver* file location
* set default marker clusterer options
* determines if traffic overlay is displayed on map
* determines if biking overlay is displayed on map
* determines whether or not to display street view controls
* ID of the container that will hold a street view if streetview controls = true.
* what server geocode lookups come from
* available: YAHOO Yahoo! API. US geocode lookups only.
* GOOGLE Google Maps. This can do international lookups,
* but not an official API service so no guarantees.
* Note: GOOGLE is the default lookup service, please read
* the Yahoo! terms of service before using their API.
* @var string service name
var $lookup_server = array('GOOGLE' => 'maps.google.com', 'YAHOO' => 'api.local.yahoo.com');
'dir_to' => 'Start address: (include addr, city st/region)',
'to_button_value' => 'Get Directions',
'to_button_type' => 'submit',
'dir_from' => 'End address: (include addr, city st/region)',
'from_button_value' => 'Get Directions',
'from_button_type' => 'submit',
'dir_text' => 'Directions: ',
'dir_tohere' => 'To here',
'dir_fromhere' => 'From here'
* maximum longitude of all markers
* minimum longitude of all markers
* determines if we should zoom to minimum level (above this->zoom value) that will encompass all markers
* factor by which to fudge the boundaries so that when we zoom encompass, the markers aren't too close to the edge
* use the first suggestion by a google lookup if exact match not found
* list of added polylines
* list of polylines that should have an elevation profile rendered.
* determines whether or not to display a marker on the "line" when
* mousing over the elevation chart
* determines whether or not to display an elevation chart
* for directions that are added to the map.
* Default icon image location.
* Default icon shadow image location.
* list of added kml overlays
* database cache table name
* Class variable that will store generated header code for JS to display directions
* Class variable that will store information to render directions
* Class variable to store whether or not to display JS functions in the header
* Class variable that will store flag to minify js - this can be overwritten after object is instantiated. Include JSMin.php if
* you want to use JS Minification.
* @param string $map_id the DOM element ID for the map
* @param string $app_id YOUR Yahoo App ID
function GoogleMapAPI($map_id = 'map', $app_id = 'MyMapApp') {
* function to enable map display
* function to disable map display (used to display street view only)
* sets the width of the map
* @return string|falseWidth or false if not a valid value
$this->width = $_width . '%';
$this->width = $_width . 'px';
* sets the height of the map
* @return string|falseHeight or false if not a valid value
$this->height = $_height . '%';
$this->height = $_height . 'px';
* sets the default map zoom level
* @param string $level Initial zoom level value
$this->zoom = (int) $level;
* enables the map controls (zoom/move)
* disables the map controls (zoom/move)
* sets the map control size (large/small)
* @param string $size Large/Small
if(in_array($size,array('large','small')))
* disable mouse scrollwheel on Map
* enables the type controls (map/satellite/hybrid)
* disables the type controls (map/satellite/hybrid)
* enables the type controls (map/satellite/hybrid)
* disables the type controls (map/satellite/hybrid)
* enables walking directions
* disables walking directions
* enables biking directions
* disables biking directions
* enables avoid highways in directions
* disables avoid highways in directions
* enables avoid tolls in directions
$this->avoid_tolls = true;
* disables avoid tolls in directions
$this->avoid_tolls = false;
* Add directions route to the map and adds text directions container with id=$dom_id
* @param string $start_address
* @param string $dest_address
* @param string $dom_id DOM Element ID for directions container.
* @param bool $add_markers Add a marker at start and dest locations.
function addDirections($start_address= '',$dest_address= '',$dom_id= '', $add_markers= true, $elevation_samples= 256, $elevation_width= "", $elevation_height= "", $elevation_dom_id= ''){
if($elevation_dom_id== "")
$elevation_dom_id = "elevation". $dom_id;
if($start_address != '' && $dest_address != '' && $dom_id != ''){
"elevation_samples"=> $elevation_samples,
"width"=> ($elevation_width!= ""? $elevation_width: str_replace("px","",$this->width)),
"height"=> ($elevation_height!= ""? $elevation_height: str_replace("px","",$this->height)/ 2),
"elevation_dom_id"=> $elevation_dom_id
* enables the type controls (map/satellite/hybrid)
* disables the type controls (map/satellite/hybrid)
* set default map type (map/satellite/hybrid)
* @param string $type New V3 Map Types, only include ending word (HYBRID,SATELLITE,TERRAIN,ROADMAP)
* enables map directions inside info window
* disables map directions inside info window
* set browser alert message for incompatible browsers
* set <noscript> message when javascript is disabled
* disable traffic overlay (default)
* disable biking overlay (default)
* disable biking overlay (default)
* attach a dom id object as a streetview container to the map
* NOTE: Only one container can be attached to a map.
* enable Google Adsense admanager on Map (not supported in V3 API)
* disable Google Adsense admanager on Map (not supported in V3 API)
* enable map marker info windows
* disable map marker info windows
* enable elevation marker to be displayed
* disable elevation marker
* enable elevation to be displayed for directions
* disable elevation to be displayed for directions
* enable map marker clustering
* disable map marker clustering
* Set clustering library file location
* set the info window trigger action
* @param string $message click/mouseover
* enable zoom to encompass makers
* disable zoom to encompass makers
* set the boundary fudge factor
* enables the scale map control
* disables the scale map control
* enables the overview map control
* disables the overview map control
* set the lookup service to use for geocode lookups
* default is YAHOO, you can also use GOOGLE.
* NOTE: GOOGLE can to intl lookups, but is not an
* official API, so use at your own risk.
* adds a map marker by address - DEPRECATION WARNING: Tabs are no longer supported in V3, if this changes this can be easily updated.
* @param string $address the map address to mark (street/city/state/zip)
* @param string $title the title display in the sidebar
* @param string $html the HTML block to display in the info bubble (if empty, title is used)
* @param string $tooltip Tooltip to display (deprecated?)
* @param string $icon_filename Web file location (eg http://somesite/someicon.gif) to use for icon
* @param string $icon_shadow_filename Web file location (eg http://somesite/someicon.gif) to use for icon shadow
function addMarkerByAddress($address,$title = '',$html = '',$tooltip = '', $icon_filename = '', $icon_shadow_filename= '') {
if(($_geocode = $this->getGeocode($address)) === false)
return $this->addMarkerByCoords($_geocode['lon'],$_geocode['lat'],$title,$html,$tooltip, $icon_filename, $icon_shadow_filename);
* adds a map marker by lat/lng coordinates - DEPRECATION WARNING: Tabs are no longer supported in V3, if this changes this can be easily updated.
* @param string $lon the map longitude (horizontal)
* @param string $lat the map latitude (vertical)
* @param string $title the title display in the sidebar
* @param string $html the HTML block to display in the info bubble (if empty, title is used)
* @param string $tooltip Tooltip to display (deprecated?)
* @param string $icon_filename Web file location (eg http://somesite/someicon.gif) to use for icon
* @param string $icon_shadow_filename Web file location (eg http://somesite/someicon.gif) to use for icon shadow
function addMarkerByCoords($lon,$lat,$title = '',$html = '',$tooltip = '', $icon_filename = '', $icon_shadow_filename= '') {
$_marker['html'] = (is_array($html) || strlen($html) > 0) ? $html : $title;
$_marker['title'] = $title;
$_marker['tooltip'] = $tooltip;
$_marker['icon_key'] = $this->setMarkerIconKey($icon_filename, $icon_shadow_filename);
if($icon_shadow_filename!= ""){
$_marker['shadow_icon']= 1;
$_marker['shadow_icon']= 1;
// return index of marker
* adds a DOM object ID to specified marker to open the marker's info window.
* Does nothing if the info windows is disabled.
* @param string $marker_id ID of the marker to associate to
* @param string $dom_id ID of the DOM object to use to open marker info window
* @return bool true/false status
if(!isset ($this->_markers[$marker_id]["openers"]))
$this->_markers[$marker_id]["openers"] = array();
$this->_markers[$marker_id]["openers"][] = $dom_id;
* adds polyline by passed array
* if color, weight and opacity are not defined, use the google maps defaults
* @param array $polyline_array array of lat/long coords
* @param string $id An array id to use to append coordinates to a line
* @param string $color the color of the line (format: #000000)
* @param string $weight the weight of the line in pixels
* @param string $opacity the line opacity (percentage)
* @return bool|intArray id of newly added point or false
foreach($polyline_array as $_coords){
$_prev_coords = $_next_coords;
$_next_coords = $_coords;
if($_prev_coords !== ""){
$_lt1= $_prev_coords["lat"];
$_ln1= $_prev_coords["long"];
$_lt2= $_next_coords["lat"];
$_ln2= $_next_coords["long"];
* adds polyline by passed array
* if color, weight and opacity are not defined, use the google maps defaults
* @param array $polyline_array array of addresses
* @param string $id An array id to use to append coordinates to a line
* @param string $color the color of the line (format: #000000)
* @param string $weight the weight of the line in pixels
* @param string $opacity the line opacity (percentage)
* @return bool|intArray id of newly added point or false
foreach($polyline_array as $_address){
$_prev_address = $_next_address;
$_next_address = $_address;
if($_prev_address !== ""){
* adds a map polyline by address
* if color, weight and opacity are not defined, use the google maps defaults
* @param string $address1 the map address to draw from
* @param string $address2 the map address to draw to
* @param string $id An array id to use to append coordinates to a line
* @param string $color the color of the line (format: #000000)
* @param string $weight the weight of the line in pixels
* @param string $opacity the line opacity (percentage)
* @return bool|intArray id of newly added point or false
if(($_geocode1 = $this->getGeocode($address1)) === false)
if(($_geocode2 = $this->getGeocode($address2)) === false)
return $this->addPolyLineByCoords($_geocode1['lon'],$_geocode1['lat'],$_geocode2['lon'],$_geocode2['lat'],$id,$color,$weight,$opacity);
* adds a map polyline by map coordinates
* if color, weight and opacity are not defined, use the google maps defaults
* @param string $lon1 the map longitude to draw from
* @param string $lat1 the map latitude to draw from
* @param string $lon2 the map longitude to draw to
* @param string $lat2 the map latitude to draw to
* @param string $id An array id to use to append coordinates to a line
* @param string $color the color of the line (format: #000000)
* @param string $weight the weight of the line in pixels
* @param string $opacity the line opacity (percentage)
* @return string $id id of the created/updated polyline array
function addPolyLineByCoords($lon1,$lat1,$lon2,$lat2,$id= false,$color= '',$weight= 0,$opacity= 0) {
//only set color,weight,and opacity if new polyline
if(!isset ($_polyline['coords']) || !is_array($_polyline['coords'])){
$_polyline['coords'] = array(
"0"=> array("lat"=> $lat1, "long"=> $lon1),
"1"=> array("lat"=> $lat2, "long"=> $lon2)
$last_index = sizeof($_polyline['coords'])- 1;
//check if lat1/lon1 point is already on polyline
if($_polyline['coords'][$last_index]["lat"] != $lat1 || $_polyline['coords'][$last_index]["long"] != $lon1){
$_polyline['coords'][] = array("lat"=> $lat1, "long"=> $lon1);
$_polyline['coords'][] = array("lat"=> $lat2, "long"=> $lon2);
// return index of polyline
* function to add an elevation profile for a polyline to the page
function addPolylineElevation($polyline_id, $elevation_dom_id, $samples= 256, $width= "", $height= "", $focus_color= "#00ff00"){
"dom_id"=> $elevation_dom_id,
"focus_color"=> $focus_color
* function to add an overlay to the map.
function addOverlay($bds_lat1, $bds_lon1, $bds_lat2, $bds_lon2, $img_src, $opacity = 100){
* function to add a KML overlay to the map.
* *Note that this expects a filename and file parsing/processing is done
* adjust map center coordinates by the given lat/lon point
* @param string $lon the map latitude (horizontal)
* @param string $lat the map latitude (vertical)
* set map center coordinates to lat/lon point
* @param string $lon the map latitude (horizontal)
* @param string $lat the map latitude (vertical)
* generate an array of params for a new marker icon image
* iconShadowImage is optional
* If anchor coords are not supplied, we use the center point of the image by default.
* Can be called statically. For private use by addMarkerIcon() and setMarkerIcon() and addIcon()
* @param string $iconImage URL to icon image
* @param string $iconShadowImage URL to shadow image
* @param string $iconAnchorX X coordinate for icon anchor point
* @param string $iconAnchorY Y coordinate for icon anchor point
* @param string $infoWindowAnchorX X coordinate for info window anchor point
* @param string $infoWindowAnchorY Y coordinate for info window anchor point
* @return array Array with information about newly /previously created icon.
function createMarkerIcon($iconImage,$iconShadowImage = '',$iconAnchorX = 'x',$iconAnchorY = 'x',$infoWindowAnchorX = 'x',$infoWindowAnchorY = 'x') {
$_icon_image_path = strpos($iconImage,'http') === 0 ? $iconImage : $_SERVER['DOCUMENT_ROOT'] . $iconImage;
die('GoogleMapAPI:createMarkerIcon: Error reading image: ' . $iconImage);
$_shadow_image_path = strpos($iconShadowImage,'http') === 0 ? $iconShadowImage : $_SERVER['DOCUMENT_ROOT'] . $iconShadowImage;
die('GoogleMapAPI:createMarkerIcon: Error reading shadow image: ' . $iconShadowImage);
if($iconAnchorX === 'x') {
$iconAnchorX = (int) ($_image_info[0] / 2);
if($iconAnchorY === 'x') {
$iconAnchorY = (int) ($_image_info[1] / 2);
if($infoWindowAnchorX === 'x') {
$infoWindowAnchorX = (int) ($_image_info[0] / 2);
if($infoWindowAnchorY === 'x') {
$infoWindowAnchorY = (int) ($_image_info[1] / 2);
'iconWidth' => $_image_info[0],
'iconHeight' => $_image_info[1],
'iconAnchorX' => $iconAnchorX,
'iconAnchorY' => $iconAnchorY,
'infoWindowAnchorX' => $infoWindowAnchorX,
'infoWindowAnchorY' => $infoWindowAnchorY
$icon_info = array_merge($icon_info, array('shadow' => $iconShadowImage,
'shadowWidth' => $_shadow_info[0],
'shadowHeight' => $_shadow_info[1]));
* set the default marker icon for ALL markers on the map
* NOTE: This MUST be set prior to adding markers in order for the defaults
* @param string $iconImage URL to icon image
* @param string $iconShadowImage URL to shadow image
* @param string $iconAnchorX X coordinate for icon anchor point
* @param string $iconAnchorY Y coordinate for icon anchor point
* @param string $infoWindowAnchorX X coordinate for info window anchor point
* @param string $infoWindowAnchorY Y coordinate for info window anchor point
* @return string A marker icon key.
function setMarkerIcon($iconImage,$iconShadowImage = '',$iconAnchorX = 'x',$iconAnchorY = 'x',$infoWindowAnchorX = 'x',$infoWindowAnchorY = 'x') {
return $this->setMarkerIconKey($iconImage,$iconShadowImage,$iconAnchorX,$iconAnchorY,$infoWindowAnchorX,$infoWindowAnchorY);
* function to check if icon is in class "marker_iconset", if it is,
* returns the key, if not, creates a new array indice and returns the key
* @param string $iconImage URL to icon image
* @param string $iconShadowImage URL to shadow image
* @param string $iconAnchorX X coordinate for icon anchor point
* @param string $iconAnchorY Y coordinate for icon anchor point
* @param string $infoWindowAnchorX X coordinate for info window anchor point
* @param string $infoWindowAnchorY Y coordinate for info window anchor point
* @return string A marker icon key.
function setMarkerIconKey($iconImage,$iconShadow= '',$iconAnchorX = 'x',$iconAnchorY = 'x',$infoWindowAnchorX = 'x',$infoWindowAnchorY = 'x'){
$_iconKey = $this->getIconKey($iconImage,$iconShadow);
return $this->addIcon($iconImage,$iconShadow,$iconAnchorX,$iconAnchorY,$infoWindowAnchorX,$infoWindowAnchorY);
* function to get icon key
* @param string $iconImage URL to marker icon image
* @param string $iconShadow URL to marker icon shadow image
* @return string Returns formatted icon key from icon or icon+shadow image name pairs
return str_replace(array("/",":","."),"",$iconImage. $iconShadow);
* add an icon to "iconset"
* @param string $iconImage URL to marker icon image
* @param string $iconShadow URL to marker icon shadow image
* @param string $iconAnchorX X coordinate for icon anchor point
* @param string $iconAnchorY Y coordinate for icon anchor point
* @param string $infoWindowAnchorX X coordinate for info window anchor point
* @param string $infoWindowAnchorY Y coordinate for info window anchor point
* @return string Returns the icon's key.
function addIcon($iconImage,$iconShadowImage = '',$iconAnchorX = 'x',$iconAnchorY = 'x',$infoWindowAnchorX = 'x',$infoWindowAnchorY = 'x') {
$_iconKey = $this->getIconKey($iconImage, $iconShadowImage);
$this->_marker_icons[$_iconKey] = $this->createMarkerIcon($iconImage,$iconShadowImage,$iconAnchorX,$iconAnchorY,$infoWindowAnchorX,$infoWindowAnchorY);
* updates a marker's icon key.
* NOTE: To be used in lieu of addMarkerIcon, now use addIcon + updateMarkerIconKey for explicit icon association
* @param string $markerKey Marker key to define which marker's icon to update
* @param string $iconKey Icon key to define which icon to use.
$this->_markers[$markerKey]['icon_key'] = $iconKey;
* print map header javascript (goes between <head></head>)
* return map header javascript (goes between <head></head>)
<meta name='viewport' content='initial-scale=1.0, user-scalable=no' />
$_headerJS .= "<script type='text/javascript' src='http://www.google.com/jsapi'></script>";
<script type='text/javascript'>
// Load the Visualization API and the piechart package.
google.load('visualization', '1', {packages: ['columnchart']});
$_headerJS .= "<script type='text/javascript' src='http://maps.google.com/maps/api/js?sensor=". (($this->mobile== true)? "true": "false"). "'></script>";
if($this->local_search){/*TODO: Load Local Search API V3 when available*/}
* prints onLoad() without having to manipulate body tag.
* call this after the print map like so...
* print onLoad function name
* return js to set onload function
return '<script language="javascript" type="text/javascript" charset="utf-8">window.onload=onLoad'. $this->map_id. ';</script>';
* return js to set onload function
return 'onLoad'. $this->map_id;
* print map javascript (put just before </body>, or in <header> if using onLoad())
$_output = '<script type="text/javascript" charset="utf-8">' . "\n";
$_output .= '//<![CDATA[' . "\n";
$_output .= "/*************************************************\n";
$_output .= " * Created with GoogleMapAPI" . $this->_version . "\n";
$_output .= " * Author: Brad Wedell <brad AT mycnl DOT com>\n";
$_output .= " * Link http://code.google.com/p/php-google-map-api/\n";
$_output .= " * Copyright 2010 Brad Wedell\n";
$_output .= " * Original Author: Monte Ohrt <monte AT ohrt DOT com>\n";
$_output .= " * Original Copyright 2005-2006 New Digital Group\n";
$_output .= " * Originial Link http://www.phpinsider.com/php/code/GoogleMapAPI/\n";
$_output .= " *************************************************/\n";
var sidebar_html$_key = '';
var marker_html$_key = [];
var markerClusterer$_key = null;
var from_htmls$_key = [];
var directions$_key = [];
var polylineCoords$_key = [];
var elevationPolylines$_key = [];
var elevationCharts$_key = [];
var kml_overlays$_key = [];
$_script .= "var icon$_key = []; \n";
//no need to check icon key here since that's already done with setters
icon". $_key. "['$icon_key'] = {};
icon". $_key. "['$icon_key'].image = new google.maps.MarkerImage('". $icon_info["image"]. "',
new google.maps.Size(". $icon_info['iconWidth']. ", ". $icon_info['iconHeight']. "),
new google.maps.Point(0,0),
new google.maps.Point(". $icon_info['iconAnchorX']. ", ". $icon_info['iconAnchorY']. ")
if(isset ($icon_info['shadow']) && $icon_info['shadow']!= ""){
icon". $_key. "['$icon_key'].shadow = new google.maps.MarkerImage('". $icon_info["shadow"]. "',
new google.maps.Size(". $icon_info['shadowWidth']. ", ". $icon_info['shadowHeight']. "),
new google.maps.Point(0,0),
new google.maps.Point(". $icon_info['iconAnchorX']. ", ". $icon_info['iconAnchorY']. ")
$_script .= "var map$_key = null;\n";
//start setting script var
$_script .= 'function onLoad'. $this->map_id. '() {' . "\n";
//TODO:Update with new browser catch - GBrowserIsCompatible is deprecated
//$_output .= 'if (GBrowserIsCompatible()) {' . "\n";
*TODO:Update with local search bar once implemented in V3 api
mapOptions.googleBarOptions= {
".(($this->local_search_ads)?",
client: '".$this->ads_pub_id."',
channel: '".$this->ads_channel."',
$strMapOptions .= ", mapOptions";
$_script .= sprintf('var mapObj%s = document.getElementById("%s");', $_key, $this->map_id) . "\n";
$_script .= "if (mapObj$_key != 'undefined' && mapObj$_key != null) {\n";
scrollwheel: ". ($this->scrollwheel? "true": "false") . ",
mapTypeId: google.maps.MapTypeId.". $this->map_type. ",
// Special care for decimal point in lon and lat, would get lost if "wrong" locale is set; applies to (s)printf only
mapOptions". $_key. ".center = new google.maps.LatLng(
mapOptions". $_key. ".streetViewControl= true;
map$_key = new google.maps.Map(mapObj$_key,mapOptions$_key);
//Add markers to the street view
//set center to last marker
//TODO:add support for Google Earth Overlay once integrated with V3
//$_output .= "map.addMapType(G_SATELLITE_3D_MAP);\n";
// zoom so that all markers are in the viewport
// increase bounds by fudge factor to keep
// markers away from the edges
$_script .= "var bds$_key = new google.maps.LatLngBounds(new google.maps.LatLng($this->_min_lat, $this->_min_lon), new google.maps.LatLng($this->_max_lat, $this->_max_lon));\n";
$_script .= 'map'. $_key. '.fitBounds(bds'. $_key. ');' . "\n";
* TODO: Update controls to use new API v3 methods.(Not a priority, see below)
* default V3 functionality caters control display according to the
* device that's accessing the page, as well as the specified width
* and height of the map itself.
if($this->map_controls) {
if($this->control_size == 'large')
$_output .= 'map.addControl(new GLargeMapControl(), new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(10,10)));' . "\n";
$_output .= 'map.addControl(new GSmallMapControl(), new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(10,60)));' . "\n";
if($this->type_controls) {
$_output .= 'map.addControl(new GMapTypeControl(), new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(10,10)));' . "\n";
if($this->scale_control) {
if($this->control_size == 'large'){
$_output .= 'map.addControl(new GScaleControl(), new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(35,190)));' . "\n";
$_output .= 'map.addControl(new GScaleControl(), new GControlPosition(G_ANCHOR_BOTTOM_RIGHT, new GSize(190,10)));' . "\n";
if($this->overview_control) {
$_output .= 'map.addControl(new GOverviewMapControl());' . "\n";
* TODO: Update with ads_manager stuff once integrated into V3
$_output .= 'var adsManager = new GAdsManager(map, "'.$this->ads_pub_id.'",{channel:"'.$this->ads_channel.'",maxAdsOnMap:"'.$this->ads_max.'"});
adsManager.enable();'."\n";
* TODO: Update with local search once integrated into V3
var trafficLayer = new google.maps.TrafficLayer();
trafficLayer.setMap(map$_key);
var bikingLayer = new google.maps.BicyclingLayer();
bikingLayer.setMap(map$_key);
kml_overlays$_key[$_kml_key]= new google.maps.KmlLayer('$_kml_file');
kml_overlays$_key[$_kml_key].setMap(map$_key);
//end JS if mapObj != "undefined" block
}//end if $this->display_map==true
//TODO:Update with new browser catch SEE ABOVE
// $_output .= '} else {' . "\n";
// $_output .= 'alert("' . str_replace('"','\"',$this->browser_alert) . '");' . "\n";
// $_output .= '}' . "\n";
$_script = JSMin::minify($_script);
//Append script to output
$_output .= '//]]>' . "\n";
$_output .= '</script>' . "\n";
* function to render utility functions for use on the page
// Utility functions used to distinguish between tabbed and non-tabbed info windows
$_script .= 'function isArray(a) {return isObject(a) && a.constructor == Array;}' . "\n";
$_script .= 'function isObject(a) {return (a && typeof a == \'object\') || isFunction(a);}' . "\n";
$_script .= 'function isFunction(a) {return typeof a == \'function\';}' . "\n";
$_script .= 'function isEmpty(obj) { for(var i in obj) { return false; } return true; }'. "\n";
* overridable function for generating js to add markers
$_output .= "var point = new google.maps.LatLng(". $_marker['lat']. ",". $_marker['lon']. ");\n";
$_output .= sprintf('%s.push(createMarker(%s%s, point,"%s","%s", %s, %s, "%s", %s ));',
(($pano== true)? $_prefix: ""). "markers". $map_id,
(isset ($_marker["icon_key"]))? "icon". $map_id. "['". $_marker["icon_key"]. "'].image": "''",
(isset ($_marker["icon_key"])&&isset ($_marker["shadow_icon"]))? "icon". $map_id. "['". $_marker["icon_key"]. "'].shadow": "''",
((isset ($_marker["openers"])&& count($_marker["openers"])> 0)? json_encode($_marker["openers"]): "''")
if($this->marker_clusterer && $pano== false){//only do marker clusterer for map, not streetview
markerClusterer". $map_id. " = new MarkerClusterer(". $_prefix. $map_id. ", markers". $map_id. ", {
* overridable function to generate polyline js - for now can only be used on a map, not a streetview
foreach($this->_polylines as $polyline_id => $_polyline) {
foreach($_polyline["coords"] as $_coords){
if($_coords_output != ""){$_coords_output.= ",";}
new google.maps.LatLng(". $_coords["lat"]. ", ". $_coords["long"]. ")
polylineCoords". $this->map_id. "[$polyline_id] = [". $_coords_output. "];
polylines". $this->map_id. "[$polyline_id] = new google.maps.Polyline({
path: polylineCoords". $this->map_id. "[$polyline_id]
". (($_polyline['color']!= "")? ", strokeColor: '". $_polyline['color']. "'": ""). "
". (($_polyline['opacity']!= 0)? ", strokeOpacity: ". $_polyline['opacity']. "": ""). "
". (($_polyline['weight']!= 0)? ", strokeWeight: ". $_polyline['weight']. "": ""). "
polylines". $this->map_id. "[$polyline_id].setMap(map". $this->map_id. ");
elevationPolylines". $this->map_id. "[$polyline_id] = {
'selector':'$elevation_dom_id',
'chart': new google.visualization.ColumnChart(document.getElementById('$elevation_dom_id')),
'service': new google.maps.ElevationService(),
'focusColor':'$focus_color',
elevationPolylines". $this->map_id. "[$polyline_id]['service'].getElevationAlongPath({
path: polylineCoords". $this->map_id. "[$polyline_id],
}, function(results,status){plotElevation(results,status, elevationPolylines". $this->map_id. "[$polyline_id], map". $this->map_id. ", elevationCharts". $this->map_id. ");});
* function to render proper calls for directions - for now can only be used on a map, not a streetview
$dom_id = $directions["dom_id"];
$travelModeParams = array();
$directionsParams .= ", \n travelMode:google.maps.DirectionsTravelMode.WALKING";
$directionsParams .= ", \n travelMode:google.maps.DirectionsTravelMode.BICYCLING";
$directionsParams .= ", \n travelMode:google.maps.DirectionsTravelMode.DRIVING";
$directionsParams .= ", \n avoidHighways: true";
$directionsParams .= ", \n avoidTolls: true";
$directionsParams .= ", \n unitSystem: google.maps.DirectionsUnitSystem.METRIC";
$directionsParams .= ", \n unitSystem: google.maps.DirectionsUnitSystem.IMPERIAL";
directions". $this->map_id. "['$dom_id'] = {
displayRenderer:new google.maps.DirectionsRenderer(),
directionService:new google.maps.DirectionsService(),
origin: '". $directions["start"]. "',
destination: '". $directions["dest"]. "'
selector: '". $directions["elevation_dom_id"]. "',
chart: new google.visualization.ColumnChart(document.getElementById('". $directions["elevation_dom_id"]. "')),
service: new google.maps.ElevationService(),
width:". $directions["width"]. ",
height:". $directions["height"]. ",
directions". $this->map_id. "['$dom_id'].displayRenderer.setMap(map". $this->map_id. ");
directions". $this->map_id. "['$dom_id'].displayRenderer.setPanel(document.getElementById('$dom_id'));
directions". $this->map_id. "['$dom_id'].directionService.route(directions". $this->map_id. "['$dom_id'].request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directions". $this->map_id. "['$dom_id'].displayRenderer.setDirections(response);
directions". $this->map_id. "['$dom_id'].service.getElevationAlongPath({
path: response.routes[0].overview_path,
samples: ". $directions["elevation_samples"]. "
}, function(results,status){plotElevation(results,status, directions". $this->map_id. "['$dom_id'], map". $this->map_id. ", elevationCharts". $this->map_id. ");});
* function to get overlay creation JS.
foreach($this->_overlays as $_key=> $_overlay){
var bounds = new google.maps.LatLngBounds(new google.maps.LatLng(". $_overlay["bounds"]["ne"]["lat"]. ", ". $_overlay["bounds"]["ne"]["long"]. "), new google.maps.LatLng(". $_overlay["bounds"]["sw"]["lat"]. ", ". $_overlay["bounds"]["sw"]["long"]. "));
var image = '". $_overlay["img"]. "';
overlays". $this->map_id. "[$_key] = new CustomOverlay(bounds, image, map". $this->map_id. ", ". $_overlay["opacity"]. ");
* overridable function to generate the js for the js function for creating a marker.
function createMarker(map, point, title, html, icon, icon_shadow, sidebar_id, openers){
if(icon!=''){marker_options.icon = icon;}
if(icon_shadow!=''){marker_options.shadow = icon_shadow;}
var new_marker = new google.maps.Marker(marker_options);
var infowindow = new google.maps.InfoWindow({content: html});
google.maps.event.addListener(new_marker, '". $this->window_trigger. "', function() {
infowindow.open(map,new_marker);
if(openers != ''&&!isEmpty(openers)){
var opener = document.getElementById(openers[i]);
opener.on". $this->window_trigger. " = function(){infowindow.open(map,new_marker); return false};
var sidebar = document.getElementById(sidebar_id);
if(sidebar!=null && sidebar!=undefined && title!=null && title!=''){
var newlink = document.createElement('a');
newlink.onclick=function(){infowindow.open(map,new_marker); return false};
newlink.onclick=function(){map.setCenter(point); return false};
newlink.innerHTML = title;
sidebar.appendChild(newlink);
CustomOverlay.prototype = new google.maps.OverlayView();
function CustomOverlay(bounds, image, map, opacity){
this.opacity = (opacity!='')?opacity:10;
CustomOverlay.prototype.onAdd = function() {
var div = document.createElement('DIV');
div.style.borderStyle = 'none';
div.style.borderWidth = '0px';
div.style.position = 'absolute';
var img = document.createElement('img');
img.style.width = '100%';
img.style.height = '100%';
img.style.opacity = this.opacity/10;
img.style.filter = 'alpha(opacity='+this.opacity*10+')';
var panes = this.getPanes();
panes.overlayImage.appendChild(div);
CustomOverlay.prototype.draw = function() {
var overlayProjection = this.getProjection();
var sw = overlayProjection.fromLatLngToDivPixel(this.bounds_.getSouthWest());
var ne = overlayProjection.fromLatLngToDivPixel(this.bounds_.getNorthEast());
div.style.left = sw.x + 'px';
div.style.top = ne.y + 'px';
div.style.width = (ne.x - sw.x) + 'px';
div.style.height = (sw.y - ne.y) + 'px';
CustomOverlay.prototype.onRemove = function() {
this.div_.parentNode.removeChild(this.div_);
* print helper function to draw elevation results as a chart
function plotElevation(results, status, elevation_data, map, charts_array) {
charts_array[elevation_data.selector] = {
data:new google.visualization.DataTable()
charts_array[elevation_data.selector].data.addColumn('string', 'Sample');
charts_array[elevation_data.selector].data.addColumn('number', 'Elevation');
for (var i = 0; i < charts_array[elevation_data.selector].results.length; i++) {
charts_array[elevation_data.selector].data.addRow(['', charts_array[elevation_data.selector].results[i].elevation]);
document.getElementById(elevation_data.selector).style.display = 'block';
elevation_data.chart.draw(charts_array[elevation_data.selector].data, {
width: elevation_data.width,
height: elevation_data.height,
focusBorderColor: elevation_data.focusColor
* create JS that is inside of JS plot elevation function
google.visualization.events.addListener(elevation_data.chart, 'onmouseover', function(e) {
if(elevation_data.marker==null){
elevation_data.marker = new google.maps.Marker({
position: charts_array[elevation_data.selector].results[e.row].location,
icon: 'http://maps.google.com/mapfiles/ms/icons/green-dot.png'
elevation_data.marker.setPosition(charts_array[elevation_data.selector].results[e.row].location);
map.setCenter(charts_array[elevation_data.selector].results[e.row].location);
document.getElementById(elevation_data.selector).onmouseout = function(){
elevation_data.marker = clearElevationMarker(elevation_data.marker);
function clearElevationMarker(marker){
* print map (put at location map will appear)
$_output = '<script type="text/javascript" charset="utf-8">' . "\n" . '//<![CDATA[' . "\n";
//$_output .= 'if (GBrowserIsCompatible()) {' . "\n";
$_output .= sprintf('document.write(\'<div id="%s" style="width: %s; height: %s; position:relative;"><\/div>\');',$this->map_id,$this->width,$this->height) . "\n";
$_output .= sprintf('document.write(\'<div id="%s" style="position:relative;"><\/div>\');',$this->map_id) . "\n";
//if(!empty($this->js_alert)) {
// $_output .= ' else {' . "\n";
// $_output .= sprintf('document.write(\'%s\');', str_replace('/','\/',$this->js_alert)) . "\n";
// $_output .= '}' . "\n";
$_output .= '//]]>' . "\n" . '</script>' . "\n";
$_output .= '<noscript>' . $this->js_alert . '</noscript>' . "\n";
* print sidebar (put at location sidebar will appear)
* get the geocode lat/lon points from given address
* look in cache first, otherwise get from Yahoo
* @return array GeoCode information
if(($_geocode = $this->getCache($address)) === false) {
$this->putCache($address, $_geocode['lon'], $_geocode['lat']);
* get the geocode lat/lon points from cache for given address
* @return bool|arrayFalse if no cache, array of data if has cache
$_db = & DB::connect($this->dsn);
if (PEAR::isError($_db)) {
$_res = & $_db->query("SELECT lon,lat FROM {$this->_db_cache_table} where address = ? ", $address);
if (PEAR::isError($_res)) {
die($_res->getMessage());
if($_row = $_res->fetchRow()) {
return !empty($_ret) ? $_ret : false;
* put the geocode lat/lon points into cache for given address
* @param string $lon the map latitude (horizontal)
* @param string $lat the map latitude (vertical)
* @return bool Status of put cache request
function putCache($address, $lon, $lat) {
if(!isset($this->dsn) || (strlen($address) == 0 || strlen($lon) == 0 || strlen($lat) == 0))
$_db = & DB::connect($this->dsn);
if (PEAR::isError($_db)) {
$_res =& $_db->query('insert into '. $this->_db_cache_table. ' values (?, ?, ?)', array($address, $lon, $lat));
if (PEAR::isError($_res)) {
die($_res->getMessage());
* get geocode lat/lon points for given address from Yahoo
* @return bool|array false if can't be geocoded, array or geocdoes if successful
function geoGetCoords($address,$depth=0) {
$_url = sprintf('http://%s/maps/api/geocode/json?sensor=%s&address=%s',$this->lookup_server['GOOGLE'], $this->mobile== true? "true": "false", rawurlencode($address));
$_result_parts = json_decode($_result);
if($_result_parts->status!= "OK"){
$_coords['lat'] = $_result_parts->results[0]->geometry->location->lat;
$_coords['lon'] = $_result_parts->results[0]->geometry->location->lng;
$_url = 'http://%s/MapsService/V1/geocode';
$_url .= sprintf('?appid=%s&location=%s',$this->lookup_server['YAHOO'],$this->app_id,rawurlencode($address));
preg_match('!<Latitude>(.*)</Latitude><Longitude>(.*)</Longitude>!U', $_result, $_match);
$_coords['lon'] = $_match[2];
$_coords['lat'] = $_match[1];
* get full geocode information for given address from Google
* NOTE: This does not use the getCache function as there is
* a lot of data in a full geocode response to cache.
* @return bool|array false if can't be geocoded, array or geocdoes if successful
function geoGetCoordsFull($address,$depth=0) {
$_url = sprintf('http://%s/maps/api/geocode/json?sensor=%s&address=%s',$this->lookup_server['GOOGLE'], $this->mobile== true? "true": "false", rawurlencode($address));
return json_decode($_result);
$_url = 'http://%s/MapsService/V1/geocode';
$_url .= sprintf('?appid=%s&location=%s',$this->lookup_server['YAHOO'],$this->app_id,rawurlencode($address));
* fetch a URL. Override this method to change the way URLs are fetched.
function fetchURL($url) {
return file_get_contents($url);
* get distance between to geocoords using great circle distance formula
* @param float $unit M=miles, K=kilometers, N=nautical miles, I=inches, F=feet
function geoGetDistance($lat1,$lon1,$lat2,$lon2,$unit='M') {
$M = 69.09 * rad2deg(acos(sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($lon1 - $lon2))));
switch(strtoupper($unit))
|