Tercer parche ->no funcional<- de implementación de Ajax con jQuery en ver+ubicaciones.
[ecomupi.git] / include / maps / GoogleMapAPI.class.php
blob08fdd8953cb155cae82098d66d2c5573e1148dfb
1 <?php
2 error_reporting(E_STRICT | E_ALL);
3 /**
4 * Project: GoogleMapAPI: a PHP library inteface to the Google Map API
5 * File: GoogleMapAPI.class.php
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * For questions, help, comments, discussion, etc., please join the
22 * Smarty mailing list. Send a blank e-mail to
23 * smarty-general-subscribe@lists.php.net
25 * @link http://www.phpinsider.com/php/code/GoogleMapAPI/
26 * @copyright 2005 New Digital Group, Inc.
27 * @author Monte Ohrt <monte at ohrt dot com>
28 * @package GoogleMapAPI
29 * @version 2.5
32 /* $Id: GoogleMapAPI.class.php,v 1.63 2007/08/03 16:29:40 mohrt Exp $ */
36 For best results with GoogleMaps, use XHTML compliant web pages with this header:
38 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
39 <html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml">
41 For database caching, you will want to use this schema:
43 CREATE TABLE GEOCODES (
44 address varchar(255) NOT NULL default '',
45 lon float default NULL,
46 lat float default NULL,
47 PRIMARY KEY (address)
52 class GoogleMapAPI {
54 /**
55 * PEAR::DB DSN for geocode caching. example:
56 * $dsn = 'mysql://user:pass@localhost/dbname';
58 * @var string
60 var $dsn = null;
62 /**
63 * YOUR GooglMap API KEY for your site.
64 * (http://maps.google.com/apis/maps/signup.html)
66 * @var string
68 var $api_key = '';
70 /**
71 * current map id, set when you instantiate
72 * the GoogleMapAPI object.
74 * @var string
76 var $map_id = null;
78 /**
79 * sidebar <div> used along with this map.
81 * @var string
83 var $sidebar_id = null;
85 /**
86 * GoogleMapAPI uses the Yahoo geocode lookup API.
87 * This is the application ID for YOUR application.
88 * This is set upon instantiating the GoogleMapAPI object.
89 * (http://developer.yahoo.net/faq/index.html#appid)
91 * @var string
93 var $app_id = null;
95 /**
96 * use onLoad() to load the map javascript.
97 * if enabled, be sure to include on your webpage:
98 * <html onload="onLoad()">
100 * @var string
102 var $onload = true;
105 * map center latitude (horizontal)
106 * calculated automatically as markers
107 * are added to the map.
109 * @var float
111 var $center_lat = null;
114 * map center longitude (vertical)
115 * calculated automatically as markers
116 * are added to the map.
118 * @var float
120 var $center_lon = null;
123 * enables map controls (zoom/move/center)
125 * @var boolean
127 var $map_controls = true;
130 * determines the map control type
131 * small -> show move/center controls
132 * large -> show move/center/zoom controls
134 * @var string
136 var $control_size = 'large';
139 * enables map type controls (map/satellite/hybrid)
141 * @var boolean
143 var $type_controls = true;
146 * default map type (G_NORMAL_MAP/G_SATELLITE_MAP/G_HYBRID_MAP)
148 * @var boolean
150 var $map_type = 'G_NORMAL_MAP';
153 * enables scale map control
155 * @var boolean
157 var $scale_control = true;
160 * enables overview map control
162 * @var boolean
164 var $overview_control = false;
167 * determines the default zoom level
169 * @var integer
171 var $zoom = 16;
174 * determines the map width
176 * @var integer
178 var $width = '500px';
181 * determines the map height
183 * @var integer
185 var $height = '500px';
188 * message that pops up when the browser is incompatible with Google Maps.
189 * set to empty string to disable.
191 * @var integer
193 var $browser_alert = 'Sorry, the Google Maps API is not compatible with this browser.';
196 * message that appears when javascript is disabled.
197 * set to empty string to disable.
199 * @var string
201 var $js_alert = '<b>Javascript must be enabled in order to use Google Maps.</b>';
204 * determines if sidebar is enabled
206 * @var boolean
208 var $sidebar = true;
211 * determines if to/from directions are included inside info window
213 * @var boolean
215 var $directions = true;
218 * determines if map markers bring up an info window
220 * @var boolean
222 var $info_window = true;
225 * determines if info window appears with a click or mouseover
227 * @var string click/mouseover
229 var $window_trigger = 'click';
232 * what server geocode lookups come from
234 * available: YAHOO Yahoo! API. US geocode lookups only.
235 * GOOGLE Google Maps. This can do international lookups,
236 * but not an official API service so no guarantees.
237 * Note: GOOGLE is the default lookup service, please read
238 * the Yahoo! terms of service before using their API.
240 * @var string service name
242 var $lookup_service = 'GOOGLE';
243 var $lookup_server = array('GOOGLE' => 'maps.google.com', 'YAHOO' => 'api.local.yahoo.com');
246 * version number
248 * @var string
250 var $_version = '2.5';
253 * list of added markers
255 * @var array
257 var $_markers = array();
260 * maximum longitude of all markers
262 * @var float
264 var $_max_lon = -1000000;
267 * minimum longitude of all markers
269 * @var float
271 var $_min_lon = 1000000;
274 * max latitude
276 * @var float
278 var $_max_lat = -1000000;
281 * min latitude
283 * @var float
285 var $_min_lat = 1000000;
288 * determines if we should zoom to minimum level (above this->zoom value) that will encompass all markers
290 * @var boolean
292 var $zoom_encompass = true;
295 * factor by which to fudge the boundaries so that when we zoom encompass, the markers aren't too close to the edge
297 * @var float
299 var $bounds_fudge = 0.01;
302 * use the first suggestion by a google lookup if exact match not found
304 * @var float
306 var $use_suggest = false;
310 * list of added polylines
312 * @var array
314 var $_polylines = array();
317 * icon info array
319 * @var array
321 var $_icons = array();
324 * database cache table name
326 * @var string
328 var $_db_cache_table = 'GEOCODES';
332 * class constructor
334 * @param string $map_id the id for this map
335 * @param string $app_id YOUR Yahoo App ID
337 function GoogleMapAPI($map_id = 'map', $app_id = 'MyMapApp') {
338 $this->map_id = $map_id;
339 $this->sidebar_id = 'sidebar_' . $map_id;
340 $this->app_id = $app_id;
344 * sets the PEAR::DB dsn
346 * @param string $dsn
348 function setDSN($dsn) {
349 $this->dsn = $dsn;
353 * sets YOUR Google Map API key
355 * @param string $key
357 function setAPIKey($key) {
358 $this->api_key = $key;
362 * sets the width of the map
364 * @param string $width
366 function setWidth($width) {
367 if(!preg_match('!^(\d+)(.*)$!',$width,$_match))
368 return false;
370 $_width = $_match[1];
371 $_type = $_match[2];
372 if($_type == '%')
373 $this->width = $_width . '%';
374 else
375 $this->width = $_width . 'px';
377 return true;
381 * sets the height of the map
383 * @param string $height
385 function setHeight($height) {
386 if(!preg_match('!^(\d+)(.*)$!',$height,$_match))
387 return false;
389 $_height = $_match[1];
390 $_type = $_match[2];
391 if($_type == '%')
392 $this->height = $_height . '%';
393 else
394 $this->height = $_height . 'px';
396 return true;
400 * sets the default map zoom level
402 * @param string $level
404 function setZoomLevel($level) {
405 $this->zoom = (int) $level;
409 * enables the map controls (zoom/move)
412 function enableMapControls() {
413 $this->map_controls = true;
417 * disables the map controls (zoom/move)
420 function disableMapControls() {
421 $this->map_controls = false;
425 * sets the map control size (large/small)
427 * @param string $size
429 function setControlSize($size) {
430 if(in_array($size,array('large','small')))
431 $this->control_size = $size;
435 * enables the type controls (map/satellite/hybrid)
438 function enableTypeControls() {
439 $this->type_controls = true;
443 * disables the type controls (map/satellite/hybrid)
446 function disableTypeControls() {
447 $this->type_controls = false;
451 * set default map type (map/satellite/hybrid)
454 function setMapType($type) {
455 switch($type) {
456 case 'hybrid':
457 $this->map_type = 'G_HYBRID_MAP';
458 break;
459 case 'satellite':
460 $this->map_type = 'G_SATELLITE_MAP';
461 break;
462 case 'map':
463 default:
464 $this->map_type = 'G_NORMAL_MAP';
465 break;
470 * enables onload
473 function enableOnLoad() {
474 $this->onload = true;
478 * disables onload
481 function disableOnLoad() {
482 $this->onload = false;
486 * enables sidebar
489 function enableSidebar() {
490 $this->sidebar = true;
494 * disables sidebar
497 function disableSidebar() {
498 $this->sidebar = false;
502 * enables map directions inside info window
505 function enableDirections() {
506 $this->directions = true;
510 * disables map directions inside info window
513 function disableDirections() {
514 $this->directions = false;
518 * set browser alert message for incompatible browsers
520 * @params $message string
522 function setBrowserAlert($message) {
523 $this->browser_alert = $message;
527 * set <noscript> message when javascript is disabled
529 * @params $message string
531 function setJSAlert($message) {
532 $this->js_alert = $message;
536 * enable map marker info windows
538 function enableInfoWindow() {
539 $this->info_window = true;
543 * disable map marker info windows
545 function disableInfoWindow() {
546 $this->info_window = false;
550 * set the info window trigger action
552 * @params $message string click/mouseover
554 function setInfoWindowTrigger($type) {
555 switch($type) {
556 case 'mouseover':
557 $this->window_trigger = 'mouseover';
558 break;
559 default:
560 $this->window_trigger = 'click';
561 break;
566 * enable zoom to encompass makers
568 function enableZoomEncompass() {
569 $this->zoom_encompass = true;
573 * disable zoom to encompass makers
575 function disableZoomEncompass() {
576 $this->zoom_encompass = false;
580 * set the boundary fudge factor
582 function setBoundsFudge($val) {
583 $this->bounds_fudge = $val;
587 * enables the scale map control
590 function enableScaleControl() {
591 $this->scale_control = true;
595 * disables the scale map control
598 function disableScaleControl() {
599 $this->scale_control = false;
603 * enables the overview map control
606 function enableOverviewControl() {
607 $this->overview_control = true;
611 * disables the overview map control
614 function disableOverviewControl() {
615 $this->overview_control = false;
620 * set the lookup service to use for geocode lookups
621 * default is YAHOO, you can also use GOOGLE.
622 * NOTE: GOOGLE can to intl lookups, but is not an
623 * official API, so use at your own risk.
626 function setLookupService($service) {
627 switch($service) {
628 case 'GOOGLE':
629 $this->lookup_service = 'GOOGLE';
630 break;
631 case 'YAHOO':
632 default:
633 $this->lookup_service = 'YAHOO';
634 break;
640 * adds a map marker by address
642 * @param string $address the map address to mark (street/city/state/zip)
643 * @param string $title the title display in the sidebar
644 * @param string $html the HTML block to display in the info bubble (if empty, title is used)
646 function addMarkerByAddress($address,$title = '',$html = '',$tooltip = '') {
647 if(($_geocode = $this->getGeocode($address)) === false)
648 return false;
649 return $this->addMarkerByCoords($_geocode['lon'],$_geocode['lat'],$title,$html,$tooltip);
653 * adds a map marker by geocode
655 * @param string $lon the map longitude (horizontal)
656 * @param string $lat the map latitude (vertical)
657 * @param string $title the title display in the sidebar
658 * @param string $html|array $html
659 * string: the HTML block to display in the info bubble (if empty, title is used)
660 * array: The title => content pairs for a tabbed info bubble
662 // TODO make it so you can specify which tab you want the directions to appear in (add another arg)
663 function addMarkerByCoords($lon,$lat,$title = '',$html = '',$tooltip = '') {
664 $_marker['lon'] = $lon;
665 $_marker['lat'] = $lat;
666 $_marker['html'] = (is_array($html) || strlen($html) > 0) ? $html : $title;
667 $_marker['title'] = $title;
668 $_marker['tooltip'] = $tooltip;
669 $this->_markers[] = $_marker;
670 $this->adjustCenterCoords($_marker['lon'],$_marker['lat']);
671 // return index of marker
672 // HACK
673 return count($this->_markers) - 1;
674 // HACK
677 // HACK
678 function deleteMarkers() {
679 unset ($this->_markers);
680 return;
683 * adds a map polyline by address
684 * if color, weight and opacity are not defined, use the google maps defaults
686 * @param string $address1 the map address to draw from
687 * @param string $address2 the map address to draw to
688 * @param string $color the color of the line (format: #000000)
689 * @param string $weight the weight of the line in pixels
690 * @param string $opacity the line opacity (percentage)
692 function addPolyLineByAddress($address1,$address2,$color='',$weight=0,$opacity=0) {
693 if(($_geocode1 = $this->getGeocode($address1)) === false)
694 return false;
695 if(($_geocode2 = $this->getGeocode($address2)) === false)
696 return false;
697 return $this->addPolyLineByCoords($_geocode1['lon'],$_geocode1['lat'],$_geocode2['lon'],$_geocode2['lat'],$color,$weight,$opacity);
701 * adds a map polyline by map coordinates
702 * if color, weight and opacity are not defined, use the google maps defaults
704 * @param string $lon1 the map longitude to draw from
705 * @param string $lat1 the map latitude to draw from
706 * @param string $lon2 the map longitude to draw to
707 * @param string $lat2 the map latitude to draw to
708 * @param string $color the color of the line (format: #000000)
709 * @param string $weight the weight of the line in pixels
710 * @param string $opacity the line opacity (percentage)
712 function addPolyLineByCoords($lon1,$lat1,$lon2,$lat2,$color='',$weight=0,$opacity=0) {
713 $_polyline['lon1'] = $lon1;
714 $_polyline['lat1'] = $lat1;
715 $_polyline['lon2'] = $lon2;
716 $_polyline['lat2'] = $lat2;
717 $_polyline['color'] = $color;
718 $_polyline['weight'] = $weight;
719 $_polyline['opacity'] = $opacity;
720 $this->_polylines[] = $_polyline;
721 $this->adjustCenterCoords($_polyline['lon1'],$_polyline['lat1']);
722 $this->adjustCenterCoords($_polyline['lon2'],$_polyline['lat2']);
723 // return index of polyline
724 return count($this->_polylines) - 1;
728 * adjust map center coordinates by the given lat/lon point
730 * @param string $lon the map latitude (horizontal)
731 * @param string $lat the map latitude (vertical)
733 function adjustCenterCoords($lon,$lat) {
734 if(strlen((string)$lon) == 0 || strlen((string)$lat) == 0)
735 return false;
736 $this->_max_lon = (float) max($lon, $this->_max_lon);
737 $this->_min_lon = (float) min($lon, $this->_min_lon);
738 $this->_max_lat = (float) max($lat, $this->_max_lat);
739 $this->_min_lat = (float) min($lat, $this->_min_lat);
741 $this->center_lon = (float) ($this->_min_lon + $this->_max_lon) / 2;
742 $this->center_lat = (float) ($this->_min_lat + $this->_max_lat) / 2;
743 return true;
747 * set map center coordinates to lat/lon point
749 * @param string $lon the map latitude (horizontal)
750 * @param string $lat the map latitude (vertical)
752 function setCenterCoords($lon,$lat) {
753 $this->center_lat = (float) $lat;
754 $this->center_lon = (float) $lon;
758 * generate an array of params for a new marker icon image
759 * iconShadowImage is optional
760 * If anchor coords are not supplied, we use the center point of the image by default.
761 * Can be called statically. For private use by addMarkerIcon() and setMarkerIcon()
763 * @param string $iconImage URL to icon image
764 * @param string $iconShadowImage URL to shadow image
765 * @param string $iconAnchorX X coordinate for icon anchor point
766 * @param string $iconAnchorY Y coordinate for icon anchor point
767 * @param string $infoWindowAnchorX X coordinate for info window anchor point
768 * @param string $infoWindowAnchorY Y coordinate for info window anchor point
770 function createMarkerIcon($iconImage,$iconShadowImage = '',$iconAnchorX = 'x',$iconAnchorY = 'x',$infoWindowAnchorX = 'x',$infoWindowAnchorY = 'x') {
771 $_icon_image_path = $iconImage;
772 if(!($_image_info = @getimagesize($_icon_image_path))) {
773 die('GoogleMapAPI:createMarkerIcon: Error reading image [1]: ' . $iconImage);
775 if($iconShadowImage) {
776 $_shadow_image_path = $iconShadowImage;
777 if(!($_shadow_info = @getimagesize($_shadow_image_path))) {
778 die('GoogleMapAPI:createMarkerIcon: Error reading image [2]: ' . $iconShadowImage);
782 if($iconAnchorX === 'x') {
783 $iconAnchorX = (int) ($_image_info[0] / 2);
785 if($iconAnchorY === 'x') {
786 $iconAnchorY = (int) ($_image_info[1] / 2);
788 if($infoWindowAnchorX === 'x') {
789 $infoWindowAnchorX = (int) ($_image_info[0] / 2);
791 if($infoWindowAnchorY === 'x') {
792 $infoWindowAnchorY = (int) ($_image_info[1] / 2);
795 $icon_info = array(
796 'image' => $iconImage,
797 'iconWidth' => $_image_info[0],
798 'iconHeight' => $_image_info[1],
799 'iconAnchorX' => $iconAnchorX,
800 'iconAnchorY' => $iconAnchorY,
801 'infoWindowAnchorX' => $infoWindowAnchorX,
802 'infoWindowAnchorY' => $infoWindowAnchorY
804 if($iconShadowImage) {
805 $icon_info = array_merge($icon_info, array('shadow' => $iconShadowImage,
806 'shadowWidth' => $_shadow_info[0],
807 'shadowHeight' => $_shadow_info[1]));
809 return $icon_info;
813 * set the marker icon for ALL markers on the map
815 function setMarkerIcon($iconImage,$iconShadowImage = '',$iconAnchorX = 'x',$iconAnchorY = 'x',$infoWindowAnchorX = 'x',$infoWindowAnchorY = 'x') {
816 $this->_icons = array($this->createMarkerIcon($iconImage,$iconShadowImage,$iconAnchorX,$iconAnchorY,$infoWindowAnchorX,$infoWindowAnchorY));
820 * add an icon to go with the correspondingly added marker
822 function addMarkerIcon($iconImage,$iconShadowImage = '',$iconAnchorX = 'x',$iconAnchorY = 'x',$infoWindowAnchorX = 'x',$infoWindowAnchorY = 'x') {
823 $this->_icons[] = $this->createMarkerIcon($iconImage,$iconShadowImage,$iconAnchorX,$iconAnchorY,$infoWindowAnchorX,$infoWindowAnchorY);
824 return count($this->_icons) - 1;
829 * print map javascript (put just before </body>, or in <header> if using onLoad())
832 function printMapJS() {
833 echo $this->getMapJS();
837 * return map javascript
840 function getMapJS() {
841 $_output = '<script type="text/javascript" charset="utf-8">' . "\n";
842 $_output .= '//<![CDATA[' . "\n";
843 $_output .= "/*************************************************\n";
844 $_output .= " * Created with GoogleMapAPI " . $this->_version . "\n";
845 $_output .= " * Author: Monte Ohrt <monte AT ohrt DOT com>\n";
846 $_output .= " * Copyright 2005-2006 New Digital Group\n";
847 $_output .= " * http://www.phpinsider.com/php/code/GoogleMapAPI/\n";
848 $_output .= " *************************************************/\n";
850 $_output .= 'var points = [];' . "\n";
851 $_output .= 'var markers = [];' . "\n";
852 $_output .= 'var counter = 0;' . "\n";
853 if($this->sidebar) {
854 $_output .= 'var sidebar_html = "";' . "\n";
855 $_output .= 'var marker_html = [];' . "\n";
858 if($this->directions) {
859 $_output .= 'var to_htmls = [];' . "\n";
860 $_output .= 'var from_htmls = [];' . "\n";
863 if(!empty($this->_icons)) {
864 $_output .= 'var icon = [];' . "\n";
865 for($i = 0, $j = count($this->_icons); $i<$j; $i++) {
866 $info = $this->_icons[$i];
868 // hash the icon data to see if we've already got this one; if so, save some javascript
869 $icon_key = md5(serialize($info));
870 if(!isset($exist_icn[$icon_key])) {
872 $_output .= "icon[$i] = new GIcon();\n";
873 $_output .= sprintf('icon[%s].image = "%s";',$i,$info['image']) . "\n";
874 if($info['shadow']) {
875 $_output .= sprintf('icon[%s].shadow = "%s";',$i,$info['shadow']) . "\n";
876 $_output .= sprintf('icon[%s].shadowSize = new GSize(%s,%s);',$i,$info['shadowWidth'],$info['shadowHeight']) . "\n";
878 $_output .= sprintf('icon[%s].iconSize = new GSize(%s,%s);',$i,$info['iconWidth'],$info['iconHeight']) . "\n";
879 $_output .= sprintf('icon[%s].iconAnchor = new GPoint(%s,%s);',$i,$info['iconAnchorX'],$info['iconAnchorY']) . "\n";
880 $_output .= sprintf('icon[%s].infoWindowAnchor = new GPoint(%s,%s);',$i,$info['infoWindowAnchorX'],$info['infoWindowAnchorY']) . "\n";
881 } else {
882 $_output .= "icon[$i] = icon[$exist_icn[$icon_key]];\n";
887 $_output .= 'var map = null;' . "\n";
889 if($this->onload) {
890 $_output .= 'function onLoad() {' . "\n";
893 if(!empty($this->browser_alert)) {
894 $_output .= 'if (GBrowserIsCompatible()) {' . "\n";
897 $_output .= sprintf('var mapObj = document.getElementById("%s");',$this->map_id) . "\n";
898 $_output .= 'if (mapObj != "undefined" && mapObj != null) {' . "\n";
899 $_output .= sprintf('map = new GMap2(document.getElementById("%s"));',$this->map_id) . "\n";
900 if(isset($this->center_lat) && isset($this->center_lon)) {
901 // Special care for decimal point in lon and lat, would get lost if "wrong" locale is set; applies to (s)printf only
902 $_output .= sprintf('map.setCenter(new GLatLng(%s, %s), %d, %s);', number_format($this->center_lat, 6, ".", ""), number_format($this->center_lon, 6, ".", ""), $this->zoom, $this->map_type) . "\n";
905 // zoom so that all markers are in the viewport
906 if($this->zoom_encompass && count($this->_markers) > 1) {
907 // increase bounds by fudge factor to keep
908 // markers away from the edges
909 $_len_lon = $this->_max_lon - $this->_min_lon;
910 $_len_lat = $this->_max_lat - $this->_min_lat;
911 $this->_min_lon -= $_len_lon * $this->bounds_fudge;
912 $this->_max_lon += $_len_lon * $this->bounds_fudge;
913 $this->_min_lat -= $_len_lat * $this->bounds_fudge;
914 $this->_max_lat += $_len_lat * $this->bounds_fudge;
916 $_output .= "var bds = new GLatLngBounds(new GLatLng($this->_min_lat, $this->_min_lon), new GLatLng($this->_max_lat, $this->_max_lon));\n";
917 $_output .= 'map.setZoom(map.getBoundsZoomLevel(bds));' . "\n";
920 if($this->map_controls) {
921 if($this->control_size == 'large')
922 $_output .= 'map.addControl(new GLargeMapControl());' . "\n";
923 else
924 $_output .= 'map.addControl(new GSmallMapControl());' . "\n";
926 if($this->type_controls) {
927 $_output .= 'map.addControl(new GMapTypeControl());' . "\n";
930 if($this->scale_control) {
931 $_output .= 'map.addControl(new GScaleControl());' . "\n";
934 if($this->overview_control) {
935 $_output .= 'map.addControl(new GOverviewMapControl());' . "\n";
938 $_output .= $this->getAddMarkersJS();
940 $_output .= $this->getPolylineJS();
942 if($this->sidebar) {
943 $_output .= sprintf('document.getElementById("%s").innerHTML = "<ul class=\"gmapSidebar\">"+ sidebar_html +"<\/ul>";', $this->sidebar_id) . "\n";
946 $_output .= '}' . "\n";
948 if(!empty($this->browser_alert)) {
949 $_output .= '} else {' . "\n";
950 $_output .= 'alert("' . str_replace('"','\"',$this->browser_alert) . '");' . "\n";
951 $_output .= '}' . "\n";
954 if($this->onload) {
955 $_output .= '}' . "\n";
958 $_output .= $this->getCreateMarkerJS();
960 // Utility functions used to distinguish between tabbed and non-tabbed info windows
961 $_output .= 'function isArray(a) {return isObject(a) && a.constructor == Array;}' . "\n";
962 $_output .= 'function isObject(a) {return (a && typeof a == \'object\') || isFunction(a);}' . "\n";
963 $_output .= 'function isFunction(a) {return typeof a == \'function\';}' . "\n";
965 if($this->sidebar) {
966 $_output .= 'function click_sidebar(idx) {' . "\n";
967 // HACK //
968 $_output .= " var titulo = document.getElementById('gmapSidebarItem_' + idx).innerHTML;\n";
969 $_output .= ' document.getElementById(\'datos_cara_mupis\').firstChild.nodeValue = loadXMLDoc(\'contenido/mupis+ubicaciones+dinamico.php?accion=mupi&amp;MUPI=\'+titulo)' . "\n";
970 // HACK //
971 $_output .= ' if(isArray(marker_html[idx])) { markers[idx].openInfoWindowTabsHtml(marker_html[idx]); }' . "\n";
972 $_output .= ' else { markers[idx].openInfoWindowHtml(marker_html[idx]); }' . "\n";
973 $_output .= '}' . "\n";
975 $_output .= 'function showInfoWindow(idx,html) {' . "\n";
976 $_output .= 'map.centerAtLatLng(points[idx]);' . "\n";
977 $_output .= 'markers[idx].openInfoWindowHtml(html);' . "\n";
978 $_output .= '}' . "\n";
979 if($this->directions) {
980 $_output .= 'function tohere(idx) {' . "\n";
981 $_output .= 'markers[idx].openInfoWindowHtml(to_htmls[idx]);' . "\n";
982 $_output .= '}' . "\n";
983 $_output .= 'function fromhere(idx) {' . "\n";
984 $_output .= 'markers[idx].openInfoWindowHtml(from_htmls[idx]);' . "\n";
985 $_output .= '}' . "\n";
988 $_output .= '//]]>' . "\n";
989 $_output .= '</script>' . "\n";
990 return $_output;
994 * overridable function for generating js to add markers
996 function getAddMarkersJS() {
997 $SINGLE_TAB_WIDTH = 88; // constant: width in pixels of each tab heading (set by google)
998 $i = 0;
999 $_output = '';
1000 foreach($this->_markers as $_marker) {
1001 if(is_array($_marker['html'])) {
1002 // warning: you can't have two tabs with the same header. but why would you want to?
1003 $ti = 0;
1004 $num_tabs = count($_marker['html']);
1005 $tab_obs = array();
1006 foreach($_marker['html'] as $tab => $info) {
1007 if($ti == 0 && $num_tabs > 2) {
1008 $width_style = sprintf(' style=\"width: %spx\"', $num_tabs * $SINGLE_TAB_WIDTH);
1009 } else {
1010 $width_style = '';
1012 $tab = str_replace('"','\"',$tab);
1013 $info = str_replace('"','\"',$info);
1014 $info = str_replace(array("\n", "\r"), "", $info);
1015 $tab_obs[] = sprintf('new GInfoWindowTab("%s", "%s")', $tab, '<div id=\"gmapmarker\"'.$width_style.'>' . $info . '</div>');
1016 $ti++;
1018 $iw_html = '[' . join(',',$tab_obs) . ']';
1019 } else {
1020 $iw_html = sprintf('"%s"',str_replace('"','\"','<div id="gmapmarker">' . str_replace(array("\n", "\r"), "", $_marker['html']) . '</div>'));
1022 $_output .= sprintf('var point = new GLatLng(%s,%s);',$_marker['lat'],$_marker['lon']) . "\n";
1023 $_output .= sprintf('var marker = createMarker(point,"%s",%s, %s,"%s");',
1024 str_replace('"','\"',$_marker['title']),
1025 str_replace('/','\/',$iw_html),
1027 str_replace('"','\"',$_marker['tooltip'])) . "\n";
1028 //TODO: in above createMarker call, pass the index of the tab in which to put directions, if applicable
1029 $_output .= 'map.addOverlay(marker);' . "\n";
1030 $i++;
1032 return $_output;
1036 * overridable function to generate polyline js
1038 function getPolylineJS() {
1039 $_output = '';
1040 foreach($this->_polylines as $_polyline) {
1041 $_output .= sprintf('var polyline = new GPolyline([new GLatLng(%s,%s),new GLatLng(%s,%s)],"%s",%s,%s);',
1042 $_polyline['lat1'],$_polyline['lon1'],$_polyline['lat2'],$_polyline['lon2'],$_polyline['color'],$_polyline['weight'],$_polyline['opacity'] / 100.0) . "\n";
1043 $_output .= 'map.addOverlay(polyline);' . "\n";
1045 return $_output;
1049 * overridable function to generate the js for the js function for creating a marker.
1051 function getCreateMarkerJS() {
1052 $_output = 'function createMarker(point, title, html, n, tooltip) {' . "\n";
1053 $_output .= 'if(n >= '. sizeof($this->_icons) .') { n = '. (sizeof($this->_icons) - 1) ."; }\n";
1054 if(!empty($this->_icons)) {
1055 $_output .= 'var marker = new GMarker(point,{\'icon\': icon[n], \'title\': tooltip});' . "\n";
1056 } else {
1057 $_output .= 'var marker = new GMarker(point,{\'title\': tooltip});' . "\n";
1059 if($this->directions) {
1060 $_output .= 'var tabFlag = isArray(html);' . "\n";
1061 $_output .= 'if(!tabFlag) { html = [{"contentElem": html}]; }' . "\n";
1062 $_output .= 'if(!tabFlag) { html = html[0].contentElem; }';
1065 if($this->info_window) {
1066 $_output .= sprintf('if(isArray(html)) { GEvent.addListener(marker, "%s", function() { marker.openInfoWindowTabsHtml(html); }); }',$this->window_trigger) . "\n";
1067 $_output .= sprintf('else { GEvent.addListener(marker, "%s", function() { marker.openInfoWindowHtml(html); alert(counter); click_sidebar(\' + counter + \'); }); }',$this->window_trigger) . "\n";
1069 $_output .= 'points[counter] = point;' . "\n";
1070 $_output .= 'markers[counter] = marker;' . "\n";
1071 if($this->sidebar) {
1072 $_output .= 'marker_html[counter] = html;' . "\n";
1073 $_output .= "sidebar_html += '<li class=\"gmapSidebarItem\" id=\"gmapSidebarItem_'+ counter +'\"><a href=\"javascript:click_sidebar(' + counter + ')\">' + title + '<\/a><\/li>';" . "\n";
1075 $_output .= 'counter++;' . "\n";
1076 $_output .= 'return marker;' . "\n";
1077 $_output .= '}' . "\n";
1078 return $_output;
1082 * print map (put at location map will appear)
1085 function printMap() {
1086 echo $this->getMap();
1090 * return map
1093 function getMap() {
1094 $_output = '';
1095 if(strlen($this->width) > 0 && strlen($this->height) > 0) {
1096 $_output .= sprintf('<div id="%s" style="width: %s; height: %s"></div>',$this->map_id,$this->width,$this->height) . "\n";
1097 } else {
1098 $_output .= sprintf('<div id="%s"></div>;',$this->map_id) . "\n";
1100 return $_output;
1105 * print sidebar (put at location sidebar will appear)
1108 function printSidebar() {
1109 echo $this->getSidebar();
1113 * return sidebar html
1116 function getSidebar() {
1117 return sprintf('<div id="%s"></div>',$this->sidebar_id) . "\n";
1121 * get the geocode lat/lon points from given address
1122 * look in cache first, otherwise get from Yahoo
1124 * @param string $address
1126 function getGeocode($address) {
1127 if(empty($address))
1128 return false;
1130 $_geocode = false;
1132 if(($_geocode = $this->getCache($address)) === false) {
1133 if(($_geocode = $this->geoGetCoords($address)) !== false) {
1134 $this->putCache($address, $_geocode['lon'], $_geocode['lat']);
1138 return $_geocode;
1142 * get the geocode lat/lon points from cache for given address
1144 * @param string $address
1146 function getCache($address) {
1147 if(!isset($this->dsn))
1148 return false;
1150 $_ret = array();
1152 // PEAR DB
1153 require_once('DB.php');
1154 $_db =& DB::connect($this->dsn);
1155 if (PEAR::isError($_db)) {
1156 die($_db->getMessage());
1158 $_res =& $_db->query("SELECT lon,lat FROM {$this->_db_cache_table} where address = ?", $address);
1159 if (PEAR::isError($_res)) {
1160 die($_res->getMessage());
1162 if($_row = $_res->fetchRow()) {
1163 $_ret['lon'] = $_row[0];
1164 $_ret['lat'] = $_row[1];
1167 $_db->disconnect();
1169 return !empty($_ret) ? $_ret : false;
1173 * put the geocode lat/lon points into cache for given address
1175 * @param string $address
1176 * @param string $lon the map latitude (horizontal)
1177 * @param string $lat the map latitude (vertical)
1179 function putCache($address, $lon, $lat) {
1180 if(!isset($this->dsn) || (strlen($address) == 0 || strlen($lon) == 0 || strlen($lat) == 0))
1181 return false;
1182 // PEAR DB
1183 require_once('DB.php');
1184 $_db =& DB::connect($this->dsn);
1185 if (PEAR::isError($_db)) {
1186 die($_db->getMessage());
1189 $_res =& $_db->query('insert into '.$this->_db_cache_table.' values (?, ?, ?)', array($address, $lon, $lat));
1190 if (PEAR::isError($_res)) {
1191 die($_res->getMessage());
1193 $_db->disconnect();
1195 return true;
1200 * get geocode lat/lon points for given address from Yahoo
1202 * @param string $address
1204 function geoGetCoords($address,$depth=0) {
1206 switch($this->lookup_service) {
1208 case 'GOOGLE':
1210 $_url = sprintf('http://%s/maps/geo?&q=%s&output=csv&key=%s',$this->lookup_server['GOOGLE'],rawurlencode($address),$this->api_key);
1212 $_result = false;
1214 if($_result = $this->fetchURL($_url)) {
1216 $_result_parts = explode(',',$_result);
1217 if($_result_parts[0] != 200)
1218 return false;
1219 $_coords['lat'] = $_result_parts[2];
1220 $_coords['lon'] = $_result_parts[3];
1223 break;
1225 case 'YAHOO':
1226 default:
1228 $_url = 'http://%s/MapsService/V1/geocode';
1229 $_url .= sprintf('?appid=%s&location=%s',$this->lookup_server['YAHOO'],$this->app_id,rawurlencode($address));
1231 $_result = false;
1233 if($_result = $this->fetchURL($_url)) {
1235 preg_match('!<Latitude>(.*)</Latitude><Longitude>(.*)</Longitude>!U', $_result, $_match);
1237 $_coords['lon'] = $_match[2];
1238 $_coords['lat'] = $_match[1];
1242 break;
1245 return $_coords;
1251 * fetch a URL. Override this method to change the way URLs are fetched.
1253 * @param string $url
1255 function fetchURL($url) {
1257 return file_get_contents($url);
1262 * get distance between to geocoords using great circle distance formula
1264 * @param float $lat1
1265 * @param float $lat2
1266 * @param float $lon1
1267 * @param float $lon2
1268 * @param float $unit M=miles, K=kilometers, N=nautical miles, I=inches, F=feet
1270 function geoGetDistance($lat1,$lon1,$lat2,$lon2,$unit='K') {
1272 // calculate miles
1273 $M = 69.09 * rad2deg(acos(sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($lon1 - $lon2))));
1275 switch(strtoupper($unit))
1277 case 'K':
1278 // kilometers
1279 return $M * 1.609344;
1280 break;
1281 case 'N':
1282 // nautical miles
1283 return $M * 0.868976242;
1284 break;
1285 case 'F':
1286 // feet
1287 return $M * 5280;
1288 break;
1289 case 'I':
1290 // inches
1291 return $M * 63360;
1292 break;
1293 case 'M':
1294 default:
1295 // miles
1296 return $M;
1297 break;