diff options
| author | ccwn <tzur@ccwn.org> | 2012-04-21 09:53:23 +0200 |
|---|---|---|
| committer | ccwn <tzur@ccwn.org> | 2012-04-21 09:53:23 +0200 |
| commit | 314328f527e8cae759d496f528a1472d7970c137 (patch) | |
| tree | 39fd79cdc6e8dd4f9cf4b8b678fb69bff9188a47 /protected | |
| parent | ed8e4f88f2877c7bed09662291711b7165e7455f (diff) | |
Extension "EGMap" hinzugefügt
Wrapper für eigene Map hinzugefügt
Marker-Icons hinzugefügt
Diffstat (limited to 'protected')
53 files changed, 9683 insertions, 0 deletions
diff --git a/protected/components/Html.php b/protected/components/Html.php new file mode 100644 index 0000000..c4a246c --- /dev/null +++ b/protected/components/Html.php @@ -0,0 +1,23 @@ +<?php +class Html extends CHtml +{ + /** + * Makes the given URL relative to the /image directory + */ + public static function imageUrl($url) { + return Yii::app()->baseUrl.'/images/'.$url; + } + /** + * Makes the given URL relative to the /css directory + */ + public static function cssUrl($url) { + return Yii::app()->baseUrl.'/css/'.$url; + } + /** + * Makes the given URL relative to the /js directory + */ + public static function jsUrl($url) { + return Yii::app()->baseUrl.'/js/'.$url; + } +} +?>
\ No newline at end of file diff --git a/protected/components/Map.php b/protected/components/Map.php new file mode 100644 index 0000000..77cb097 --- /dev/null +++ b/protected/components/Map.php @@ -0,0 +1,49 @@ +<?php +class Map { + private $POS_LAT; + private $POS_LONG; + private $gMap; + private $publishedIcon; + private $notPublishedIcon; + + public function __construct() { + $this->POS_LAT = Yii::app()->params["pos_lat"]; + $this->POS_LONG = Yii::app()->params["pos_long"]; + $this->gMap = new EGMap(); + $this->gMap->setAPIKey(Yii::app()->params["map_api_domain"], Yii::app()->params["map_api_key"]); + $this->gMap->setWidth(880); + $this->gMap->setHeight(550); + $this->gMap->zoom = 18; + $mapTypeControlOptions = array( + 'position' => EGMapControlPosition::RIGHT_TOP, + 'style' => EGMap::MAPTYPECONTROL_STYLE_HORIZONTAL_BAR + ); + + $this->gMap->mapTypeId = EGMap::TYPE_HYBRID; + $this->gMap->mapTypeControlOptions = $mapTypeControlOptions; + $this->gMap->zoom = 18; + $this->gMap->setCenter($this->POS_LAT, $this->POS_LONG); + + // Green icon for published standorte for marker. + $this->publishedIcon = new EGMapMarkerImage(Html::imageUrl("map/marker_green_32.png")); + $this->publishedIcon->setSize(32, 37); + $this->publishedIcon->setAnchor(16, 16.5); + $this->publishedIcon->setOrigin(0, 0); + // Red icon for non-published standorte for marker. + $this->notPublishedIcon = new EGMapMarkerImage(Html::imageUrl("map/marker_red_32.png")); + $this->notPublishedIcon->setSize(32, 37); + $this->notPublishedIcon->setAnchor(16, 16.5); + $this->notPublishedIcon->setOrigin(0, 0); + } + + public function addMarker(EGMapMarker $marker, $published) { + $options = $marker->getOptions(); + $newOptions = array_merge($options, array("icon"=>(($published) ? $this->publishedIcon : $this->notPublishedIcon))); + $marker->setOptions($newOptions); + $this->gMap->addMarker($marker); + } + + public function render() { + $this->gMap->renderMap(array(), Yii::app()->language); + } +}
\ No newline at end of file diff --git a/protected/controllers/StandortController.php b/protected/controllers/StandortController.php new file mode 100644 index 0000000..3fa11df --- /dev/null +++ b/protected/controllers/StandortController.php @@ -0,0 +1,190 @@ +<?php + +class StandortController extends Controller +{ + /** + * @var string the default layout for the views. Defaults to '//layouts/column2', meaning + * using two-column layout. See 'protected/views/layouts/column2.php'. + */ + public $layout='//layouts/column2'; + + /** + * @return array action filters + */ + public function filters() + { + return array( + 'accessControl', // perform access control for CRUD operations + ); + } + + /** + * Specifies the access control rules. + * This method is used by the 'accessControl' filter. + * @return array access control rules + */ + public function accessRules() + { + return array( + array('allow', // allow admin user to perform 'admin' and 'delete' actions + 'actions'=>array('delete','create','update','index','view','ajaxupdate','ajaxcreate','savecoords'), + 'users'=>array('admin'), + ), + array('deny', // deny all users + 'users'=>array('*'), + ), + ); + } + + /** + * Displays a particular model. + * @param integer $id the ID of the model to be displayed + */ + public function actionView($id) + { + $this->render('view',array( + 'model'=>$this->loadModel($id), + )); + } + + /** + * Creates a new model. + * If creation is successful, the browser will be redirected to the 'view' page. + */ + public function actionCreate() + { + $model=new Standort; + + // Uncomment the following line if AJAX validation is needed + // $this->performAjaxValidation($model); + + if(isset($_POST['Standort'])) + { + $model->attributes=$_POST['Standort']; + if($model->save()) + $this->redirect(array('index')); + } + + $this->render('create',array( + 'model'=>$model, + )); + } + + /** + * Updates a particular model. + * If update is successful, the browser will be redirected to the 'view' page. + * @param integer $id the ID of the model to be updated + */ + public function actionUpdate($id) + { + $model=$this->loadModel($id); + + // Uncomment the following line if AJAX validation is needed + // $this->performAjaxValidation($model); + + if(isset($_POST['Standort'])) + { + $model->attributes=$_POST['Standort']; + if($model->save()) + $this->redirect(array('view','id'=>$model->id)); + } + + $this->render('update',array( + 'model'=>$model, + )); + } + + + /** + * Updates the standort with $id. + * This method loads the post parameters + * <ul> + * <li>lat</li> + * <li>lng</li> + * </ul> + * @param integer $id the ID of the standort to be moved + * @throws CHttpException if + * <ul> + * <li>one of the parameters is not set or</li> + * <li>the standort does not exist or</li> + * <li>the save action was unsuccessful</li> + * </ul> + */ + public function actionSavecoords($id) { + $model=$this->loadModel($id); + + if (isset($_POST['lat']) && isset($_POST['lng'])) { + $model->pos_lat = $_POST['lat']; + $model->pos_long = $_POST['lng']; + if($model->save()) { + echo "success"; + } else { + throw new CHttpException(500, "Could not save"); + } + } else { + throw new CHttpException(400, "Wrong parameters"); + } + } + + /** + * Deletes a particular model. + * If deletion is successful, the browser will be redirected to the 'admin' page. + * @param integer $id the ID of the model to be deleted + */ + public function actionDelete($id) + { + if(Yii::app()->request->isPostRequest) + { + // we only allow deletion via POST request + $this->loadModel($id)->delete(); + + // if AJAX request (triggered by deletion via admin grid view), we should not redirect the browser + if(!isset($_GET['ajax'])) + $this->redirect(isset($_POST['returnUrl']) ? $_POST['returnUrl'] : array('admin')); + } + else + throw new CHttpException(400,'Invalid request. Please do not repeat this request again.'); + } + + /** + * Manages all models. + */ + public function actionIndex() + { + $model=new Standort('search'); + $model->unsetAttributes(); // clear any default values + if(isset($_GET['Standort'])) + $model->attributes=$_GET['Standort']; + + $this->render('index',array( + 'model'=>$model, + "standorte"=>Standort::model()->findAll() + )); + } + + /** + * Returns the data model based on the primary key given in the GET variable. + * If the data model is not found, an HTTP exception will be raised. + * @param integer the ID of the model to be loaded + */ + public function loadModel($id) + { + $model=Standort::model()->findByPk($id); + if($model===null) + throw new CHttpException(404,'The requested page does not exist.'); + return $model; + } + + /** + * Performs the AJAX validation. + * @param CModel the model to be validated + */ + protected function performAjaxValidation($model) + { + if(isset($_POST['ajax']) && $_POST['ajax']==='standort-form') + { + echo CActiveForm::validate($model); + Yii::app()->end(); + } + } +} diff --git a/protected/extensions/egmap/.DS_Store b/protected/extensions/egmap/.DS_Store Binary files differnew file mode 100644 index 0000000..5008ddf --- /dev/null +++ b/protected/extensions/egmap/.DS_Store diff --git a/protected/extensions/egmap/EGMap.php b/protected/extensions/egmap/EGMap.php new file mode 100644 index 0000000..3b3dd6c --- /dev/null +++ b/protected/extensions/egmap/EGMap.php @@ -0,0 +1,1361 @@ +<?php + +/** + * + * EGMap Google Map class + * Inspired from + * the amazing work of Symphony + * GMap class. + * + * I try to keep comments of the authors to + * functions + * + * @link https://github.com/fabriceb/sfEasyGMapPlugin + * + * @author Antonio Ramirez Cobos + * @link http://www.ramirezcobos.com + * + * @copyright + * info as this library is a modified version of Fabrice Bernhard + * + * Copyright (c) 2008 Fabrice Bernhard + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +class EGMap extends EGMapBase { + // This map type displays a normal street map. + const TYPE_ROADMAP = 'google.maps.MapTypeId.ROADMAP'; + // This map type displays maps with physical features such as terrain and vegetation. + const TYPE_TERRAIN = 'google.maps.MapTypeId.TERRAIN'; + // This map type displays a transparent layer of major streets on satellite images. + const TYPE_HYBRID = 'google.maps.MapTypeId.HYBRID'; + // This map type displays satellite images. + const TYPE_SATELLITE = 'google.maps.MapTypeId.SATELLITE'; + + // displays the array of controls as buttons in a horizontal bar as is shown on Google Maps. + const MAPTYPECONTROL_STYLE_HORIZONTAL_BAR = 'google.maps.MapTypeControlStyle.HORIZONTAL_BAR'; + // displays a single button control allowing you to select the map type via a dropdown menu. + const MAPTYPECONTROL_STYLE_DROPDOWN_MENU = 'google.maps.MapTypeControlStyle.DROPDOWN_MENU'; + // displays the "default" behavior, which depends on screen size and may change in future versions of the API + const MAPTYPECONTROL_STYLE_DEFAULT = 'google.maps.MapTypeControlStyle.DEFAULT'; + + // displays a mini-zoom control, consisting of only + and - buttons. This + // style is appropriate for small maps. On touch devices, this control displays + // as + and - buttons that are responsive to touch + const ZOOMCONTROL_STYLE_SMALL = 'google.maps.ZoomControlStyle.SMALL'; + // displays the standard zoom slider control. On touch devices, this control + // displays as + and - buttons that are responsive to touch events. + const ZOOMCONTROL_STYLE_LARGE = 'google.maps.ZoomControlStyle.LARGE'; + // picks an appropriate zoom control based on the map's size and the device on + // which the map is running. + const ZOOMCONTROL_STYLE_DEFAULT = 'google.maps.ZoomControlStyle.DEFAULT'; + + /** + * + * Available plugins + * @var array + */ + private $plugins = array( + 'EGMapMarkerWithLabel' => array('js' => array('markerwithlabel_packed.js'), 'flag' => false), + 'EGMapKeyDragZoom' => array('js' => array('keydragzoom_packed.js'), 'flag' => false), + 'EGMapMarkerClusterer' => array('js' => array('markerclusterer_packed.js'), 'flag' => false), + 'EGMapLatLonControl' => array('js' => array('latloncontrol.js'), 'flag' => false), + 'EGMapKMLService' => array('js' => array('geoxml3.js'), 'flag' => false), + 'EGMapInfoBox' => array('js'=> array('infobox_packed.js'), 'flag'=> false) + ); + + /** + * + * Folder reference to the registered plugin assets + * @var string + */ + private $pluginDir = null; + + /** + * + * HTML document Id + * @var string + */ + private $_containerId; + + /** + * + * Container HTML attributes + * @var array + */ + private $_htmlOptions = array(); + + /** + * + * Container CSS options + * <pre> + * array('width'=>'512px','height'=>'512px'); + * </pre> + * @var array + */ + private $_styleOptions = array('width' => '512px', 'height' => '512px'); + + /** + * + * default Google Map Options + * @var array + */ + protected $options = array( + // boolean If true, do not clear the contents of the Map div. + 'noClear ' => null, + // Enables/disables zoom and center on double click. true by default. + 'disableDoubleClickZoom' => null, + // string Color used for the background of the Map div. This color will be visible when tiles have not yet loaded as a user pans. + 'backgroundColor' => null, + // string The name or url of the cursor to display on a draggable object. + 'draggableCursor' => null, + // string The name or url of the cursor to display when an object is dragging. + 'draggingCursor' => null, + // boolean If false, prevents the map from being dragged. Dragging is enabled by default. + 'draggable' => null, + // boolean If true, enables scrollwheel zooming on the map. The scrollwheel is disabled by default. + 'scrollwheel' => null, + // boolean If false, prevents the map from being controlled by the keyboard. Keyboard shortcuts are enabled by default. + 'keyboardShortcuts' => null, + // LatLng The initial Map center. Required. + 'center' => null, + // number The initial Map zoom level. Required. + 'zoom' => null, + // The maximum zoom level which will be displayed on the map. If omitted, or set to + // null, the maximum zoom from the current map type is used instead. + 'maxZoom' => null, + // The minimum zoom level which will be displayed on the map. If omitted, or set to + // null, the minimum zoom from the current map type is used instead. + 'minZoom' => null, + // The enabled/disabled state of the zoom control. + // true by default + 'zoomControl' => null, + // http://code.google.com/intl/en-EN/apis/maps/documentation/javascript/reference.html#ZoomControlStyle + 'zoomControlStyle' => null, + // Of type named array + // http://code.google.com/intl/en-EN/apis/maps/documentation/javascript/reference.html#ZoomControlOptions + 'zoomControlOptions' => null, + // The initial enabled/disabled state of the Street View pegman control. + 'streetViewControl' => null, + // The initial display options for the Street View pegman control. + // Of type named array + // http://code.google.com/intl/en-EN/apis/maps/documentation/javascript/reference.html#streetViewControlOptions + 'streetViewControlOptions' => null, + // string The initial Map mapTypeId. Required. + 'mapTypeId' => self::TYPE_ROADMAP, + // boolean Enables/disables all default UI. May be overridden individually. + 'disableDefaultUI' => null, + // boolean The initial enabled/disabled state of the Map type control. + 'mapTypeControl' => null, + // MapTypeControl options The initial display options for the Map type control. + // Of type named array + // http://code.google.com/intl/en-EN/apis/maps/documentation/javascript/reference.html#MapTypeControlOptions + 'mapTypeControlOptions' => null, + // The enabled/disabled state of the pan control. + 'panControl' => null, + // The display options for the pan control. + // http://code.google.com/intl/en-EN/apis/maps/documentation/javascript/reference.html#PanControlOptions + 'panControlOptions' => null, + // boolean The initial enabled/disabled state of the scale control. + 'scaleControl' => null, + // ScaleControl options The initial display options for the scale control. + // http://code.google.com/intl/en-EN/apis/maps/documentation/javascript/reference.html#ScaleControlOptions + // Of type named array + 'scaleControlOptions' => null, + // boolean The initial enabled/disabled state of the navigation control. + 'navigationControl' => null, + // NavigationControl options The initial display options for the navigation control. + // http://code.google.com/intl/en-EN/apis/maps/documentation/javascript/3.2/reference.html#NavigationControlOptions + // Of type named array + 'navigationControlOptions' => null + ); + + /** + * + * Where the map should be appended to + * (refer to registerMap Script) + * It can be any valid javascript #id identifier + */ + private $_appendTo = null; + + /** + * + * If enabled will hold a reference to a + * EGMapKeyDragZoom object + * @var EGMapKeyDragZoom + */ + private $_keyDrag = null; + + /** + * + * If enabled will hold a reference to a + * EGMapClusteredManager object + */ + private $_markerClusterer = null; + + /** + * + * If enabled will hold a reference to a + * EGMapLatLonControl object + */ + private $_latLonControl = null; + + /** + * + * If enabled will hold a reference to a + * EGMapKMLService object + */ + private $_kmlService = null; + + /** + * @todo replace following variables to + * a CMap object with CTypedList | CTypedMap Collections + * $resources = new CMap() + * $resources['markers'] = new CTypedList('EGMapMarker'); + * $resources['variables'] = new CMap(); + * $resources['events'] + */ + protected $resources; + + /** + * the interface to the Google Maps API web service + */ + protected $gMapClient = null; + + /** + * Constructs a Google Map PHP object + * + * @param array $options Google Map Options + * @param array $htmlOptions Container HTML attributes + */ + public function __construct($options=array(), $htmlOptions=array()) + { + + $this->resources = new CMap(); + + $this->setOptions($options); + $this->setHtmlOptions($htmlOptions); + + $this->gMapClient = new EGMapClient(); + } + + /** + * + * Sets the HTML attributes of the container + * @param array $options + */ + public function setHtmlOptions($options) + { + if (is_scalar($options)) + return; + $this->_htmlOptions = array_merge($this->_htmlOptions, $options); + } + + /** + * + * Returns the HTML attributes of the container + * @return array + */ + public function getHtmlOptions() + { + return $this->_htmlOptions; + } + + /** + * + * Sets Google Map Options + * @param array $options + * + */ + public function setOptions($options) + { + $this->options = CMap::mergeArray($this->options, $options); + } + + /** + * + * Returns the Google API key + * @see EGMapClient + * @return string $key + */ + public function getAPIKey() + { + return $this->getGMapClient()->getAPIKey(); + } + + /** + * + * Sets a Google API key for a specific domain + * @param string $domain + * @param string $key + */ + public function setAPIKey($domain, $key) + { + $this->getGMapClient()->setAPIKey($domain, $key, true); + } + + /** + * Gets an instance of the interface to the Google Map web geocoding service + * + * @return EGMapClient + */ + public function getGMapClient() + { + if (null === $this->gMapClient) + $this->gMapClient = new EGMapClient(); + + return $this->gMapClient; + } + + /** + * Sets an instance of the interface to the Google Map web geocoding service + * + * @param EGMapClient + */ + public function setGMapClient($gMapClient) + { + $this->gMapClient = $gMapClient; + } + + /** + * Geocodes an address + * @param string $address + * @return GMapGeocodedAddress + * @author Fabrice Bernhard + */ + public function geocode($address) + { + $address = trim($address); + + $gMapGeocodedAddress = new EGMapGeocodedAddress($address); + $accuracy = $gMapGeocodedAddress->geocode($this->getGMapClient()); + + if ($accuracy) + return $gMapGeocodedAddress; + + return null; + } + + /** + * Geocodes an address and returns additional normalized information + * @param string $address + * @return GMapGeocodedAddress + * @author Fabrice Bernhard + * @since 2010-12-22 Yii Modified Antonio Ramirez + */ + public function geocodeXml($address) + { + $address = trim($address); + + $gMapGeocodedAddress = new EGMapGeocodedAddress($address); + $gMapGeocodedAddress->geocodeXml($this->getGMapClient()); + + return $gMapGeocodedAddress; + } + + /** + * Returns the ID of the widget or generates a new one if requested. + * @param boolean $autoGenerate whether to generate an ID if it is not set previously + * @return string id of the widget. + * @author Antonio Ramirez + */ + public function getContainerId($autoGenerate=true) + { + if ($this->_containerId !== null) + return $this->_containerId; + else if ($autoGenerate) + return $this->_containerId = 'EGMapContainer' . parent::$_counter++; + } + + /** + * + * Sets content layer ID + * @param integer $id + * @author Antonio Ramirez + */ + public function setContainerId($id) + { + $this->_containerId = $id; + } + + /** + * + * Sets the id of the layer where the maps should be rendered + * @param string $id ie. #idcontainer + */ + public function appendMapTo($id) + { + if (substr(ltrim($id), 0, 1) != '#' && $id != 'body') + throw new CException(Yii::t('EGMap', 'The id of the layer doesnt seem a correct ID (not CSS selector) <br/>Function: ' . __FUNCTION__)); + $this->_appendTo = $id; + } + + /** + * Defines one attributes of the div container + * Styles are defined differently + * @link $this->setStyles + * @param array $htmlOptions of attributes + * @author Antonio Ramirez + */ + public function setContainerOptions($htmlOptions) + { + if (is_scalar($htmlOptions)) + throw new CException(Yii::t('EGMap', 'setContainerOptions: $htmlOptions must be an array')); + + if (isset($htmlOptions['id'])) + $this->setContainerId($htmlOptions['id']); + $this->_htmlOptions = $htmlOptions; + } + + /** + * + * Returns the attribute options of the container + * @return array htmlOptions + * @author Antonio Ramirez + */ + public function getContainerOptions() + { + return $this->_htmlOptions; + } + + /** + * returns the Html for the Google map container + * @param Array $options Style options of the HTML container + * @return string $container + * @since 2010-12-22 Yii modified Antonio Ramirez + */ + public function getContainer($styles=array(), $attributes=array()) + { + $options = array_merge($this->_htmlOptions, array('id' => $this->getContainerId())); + if (!isset($options['style'])) + $options['style'] = ''; + + foreach ($this->_styleOptions as $style => $value) + { + $options['style'] .= $style . ':' . $value . ';'; + } + + return CHtml::tag('div', $options, '', true); + } + + /** + * + * @return string + * @author fabriceb + * @since 2009-08-20 + * @since 2011-01-21 Modified by Antonio Ramirez + * Improved algorithm + */ + public function optionsToJs() + { + return $this->encode($this->options); + } + + /** + * + * Registers the Javascript required for the Google map + * @param array $afterInit -javascript code to be rendered after init call + * @param string $language -preferred language setting for the results + * @param string $region -top level geographic domain + * @param ClientScript::CONSTANT $position -where to render the script + * @since 2010-12-22 Antonio Ramirez (inspired by sfGMap Plugin of Fabriceb) + * @since 2011-01-09 Antonio Ramirez + * removed deprecated initialization procedures //$init_events[] = $this->getIconsJs(); + * @since 2011-01-22 Antonio Ramirez + * Added support for key drag and marker clusterer plugin + * @since 2011-03-10 Matt Kay + * Added polygon support (added to init_events) + * @since 2011-03-23 Antonio Ramirez + * Added circles and rectangles support + */ + public function registerMapScript($afterInit=array(), $language = null, $region = null, $position = CClientScript::POS_LOAD) + { + // TODO: include support in the future + $params = 'sensor=false'; + + if ($language !== null) + $params .= '&language=' . $language; + if ($region !== null) + $params .= '®ion=' . $region; + + CGoogleApi::init(); + CGoogleApi::register('maps', '3', array('other_params' => $params)); + + $this->registerPlugins(); + + $js = ''; + + $init_events = array(); + if (null !== $this->_appendTo) + { + $init_events[] = "$('{$this->getContainer()}').appendTo('{$this->_appendTo}');" . PHP_EOL; + } + $init_events[] = 'var mapOptions = ' . $this->encode($this->options) . ';' . PHP_EOL; + $init_events[] = $this->getJsName() . ' = new google.maps.Map(document.getElementById("' . $this->getContainerId() . '"), mapOptions);' . PHP_EOL; + + + // add some more events + $init_events[] = $this->getEventsJs(); + $init_events[] = $this->getMarkersJs(); + $init_events[] = $this->getDirectionsJs(); + $init_events[] = $this->getPluginsJs(); + $init_events[] = $this->getPolygonsJs(); + $init_events[] = $this->getCirclesJs(); + $init_events[] = $this->getRectanglesJs(); + + if (is_array($afterInit)) + { + foreach ($afterInit as $ainit) + $init_events[] = $ainit; + } + if ($this->getGlobalVariable($this->getJsName() . '_info_window')) + $init_events[] = $this->getJsName() . '_info_window=new google.maps.InfoWindow();'; + if ($this->getGlobalVariable($this->getJsName() . '_info_box') && $this->resources->itemAt('infobox_config')) + $init_events[] = $this->getJsName (). '_info_box=new InfoBox('. + $this->resources->itemAt('infobox_config').');'; + + // declare the Google Map Javascript object as global + $this->addGlobalVariable($this->getJsName(), 'null'); + + $js = $this->getGlobalVariables(); + + Yii::app()->getClientScript()->registerScript('EGMap_' . $this->getJsName(), $js, CClientScript::POS_HEAD); + + $js = 'function ' . $this->_containerId . '_init(){' . PHP_EOL; + foreach ($init_events as $init_event) + { + if ($init_event) + { + $js .= $init_event . PHP_EOL; + } + } + $js .= ' + } google.maps.event.addDomListener(window, "load",' . PHP_EOL . $this->_containerId . '_init);' . PHP_EOL; + + Yii::app()->getClientScript()->registerScript($this->_containerId . time(), $js, CClientScript::POS_END); + } + + /** + * @return string javascript code from plugins + */ + public function getPluginsJs() + { + $return = ''; + if (null !== $this->_markerClusterer) + $return .= $this->_markerClusterer->toJs($this->getJsName()); + if (null !== $this->_keyDrag) + $return .= $this->_keyDrag->toJs($this->getJsName()); + if (null !== $this->_latLonControl) + $return .= $this->_latLonControl->toJs($this->getJsName()); + if (null !== $this->_kmlService) + $return .= $this->_kmlService->toJs($this->getJsName()); + return $return; + } + + /** + * + * Enables LatLonControl plugin + * + */ + public function enableKMLService($url, $localhost = false) + { + if (true === $localhost) + $this->registerPlugin('EGMapKMLService'); + $this->_kmlService = new EGMapKMLService($url); + } + + /** + * + * Disables LatLonControl plugin + */ + public function disableKMLService() + { + $this->registerPlugin('EGMapKMLService', false); + $this->_kmlService = null; + } + + /** + * + * Enables LatLonControl plugin + * + */ + public function enableLatLonControl() + { + $this->registerPlugin('EGMapLatLonControl'); + $this->_latLonControl = new EGMapLatLonControl(); + } + + /** + * + * Disables LatLonControl plugin + */ + public function disableLatLonControl() + { + $this->registerPlugin('EGMapLatLonControl', false); + $this->_latLonControl = null; + } + + /** + * + * Enables Marker Clusterer Plugin + * @param EGMapMarkerClusterer $markerclusterer + * @author Antonio Ramirez + */ + public function enableMarkerClusterer(EGMapMarkerClusterer $markerclusterer) + { + $this->registerPlugin('EGMapMarkerClusterer'); + $this->_markerClusterer = $markerclusterer; + } + + /** + * + * Disables Marker Clusterer Plugin + * @author Antonio Ramirez + */ + public function disableMarkerClusterer() + { + $this->registerPlugin('EGMapMarkerClusterer'); + $this->_markerClusterer = null; + } + + /** + * + * Enables Key drag Zoom plugin + * @param EGMapKeyDragZoom $dragzoom + * @author Antonio Ramirez + */ + public function enableKeyDragZoom(EGMapKeyDragZoom $dragzoom) + { + $this->registerPlugin('EGMapKeyDragZoom'); + $this->_keyDrag = $dragzoom; + } + + /** + * + * Disables Key Drag Zoom Plugin + */ + public function disableKeyDragZoom() + { + $this->registerPlugin('EGMapKeyDragZoom', false); + $this->_keyDrag = null; + } + + /** + * + * Lazy Programmer's function to register the javascript needed and display HTML + * map container + * @param array $afterInit -javascript code to be rendered after init call + * @param string $language -preferred language setting for the results + * @param string $region -top level geographic domain + * @param ClientScript::CONSTANT $position -where to render the script + */ + public function renderMap($afterInit=array(), $language = null, $region = null, $position = CClientScript::POS_LOAD) + { + + $this->registerMapScript($afterInit, $language, $region, $position); + if (null === $this->_appendTo) + echo $this->getContainer(); + } + + /** + * @param EGMapMarker $marker a marker to be put on the map + * @since 2011-01-11 added support for global infowindow + * @since 2011-01-22 added support for EGMapMarkerWithLabel plugin + * @since 2011-01-23 fixed info window shared + */ + public function addMarker(EGMapMarker $marker) + { + if (null === $this->resources->itemAt('markers')) + $this->resources->add('markers', new CTypedList('EGMapMarker')); + if ($marker->getHtmlInfoWindow() && $marker->htmlInfoWindowShared() && !$this->getGlobalVariable($this->getJsName() . '_info_window')) + $this->addGlobalVariable($this->getJsName() . '_info_window', 'null'); + if ($marker->getHtmlInfoBox() && $marker->htmlInfoBoxShared() && !$this->getGlobalVariable($this->getJsName() . '_info_box')) + { + $this->addGlobalVariable($this->getJsName() . '_info_box', 'null'); + $this->resources->add('infobox_config',$marker->getHtmlInfoBox()->getEncodedOptions()); + $this->registerPlugin('EGMapInfoBox'); + } + if ($marker instanceof EGMapMarkerWithLabel && !$this->pluginRegistered('EGMapMarkerWithLabel')) + $this->registerPlugin('EGMapMarkerWithLabel'); + $this->resources->itemAt('markers')->add($marker); + } + + /** + * @param EGMapPolygon $polygon a polygon to be put on the map + * @since 2011-03-10 Matt Kay + * Added this function for polygons based on addMarker + * @since 2011-17-12 Added info window support + */ + public function addPolygon(EGMapPolygon $polygon) + { + if (null === $this->resources->itemAt('polygons')) + $this->resources->add('polygons', new CTypedList('EGMapPolygon')); + if ($polygon->getHtmlInfoWindow() && $polygon->htmlInfoWindowShared() && !$this->getGlobalVariable($this->getJsName() . '_info_window')) + $this->addGlobalVariable($this->getJsName() . '_info_window', 'null'); + $this->resources->itemAt('polygons')->add($polygon); + } + + /** + * @param EGMapCircle $circle a circle to be put on the map + * @since 2011-03-23 Antonio Ramirez Cobos + */ + public function addCircle(EGMapCircle $circle) + { + if (null === $this->resources->itemAt('circles')) + $this->resources->add('circles', new CTypedList('EGMapCircle')); + if ($circle->getHtmlInfoWindow() && $circle->htmlInfoWindowShared() && !$this->getGlobalVariable($this->getJsName() . '_info_window')) + $this->addGlobalVariable($this->getJsName() . '_info_window', 'null'); + $this->resources->itemAt('circles')->add($circle); + } + + /** + * @param EGMapRectangle $rectangle a rectangle to be put on the map + * @since 2011-03-23 Antonio Ramirez Cobos + */ + public function addRectangle(EGMapRectangle $rectangle) + { + if (null === $this->resources->itemAt('rectangles')) + $this->resources->add('rectangles', new CTypedList('EGMapRectangle')); + if ($rectangle->getHtmlInfoWindow() && $rectangle->htmlInfoWindowShared() && !$this->getGlobalVariable($this->getJsName() . '_info_window')) + $this->addGlobalVariable($this->getJsName() . '_info_window', 'null'); + $this->resources->itemAt('rectangles')->add($rectangle); + } + /** + * @param EGMapMarker[] $markers marker to be put on the map + * @since 2011-01-22 Antonio Ramirez + * Added support for EGMapMarkerWithLabel plugin + */ + public function setMarkers(CTypedList $markers) + { + foreach ($markers as $marker) + { + if (!$marker instanceof EGMapMarker) + throw new CException(Yii::t('EGMap', 'Markers collection must be of base class EGMapMarker')); + if ($marker instanceof EGMapMarkerWithLabel && !$this->pluginRegistered('EGMapMarkerWithLabel')) + $this->registerPlugin('EGMapMarkerWithLabel'); + } + $this->resources->add('markers', $markers); + } + + /** + * @param EGMapEvent $event an event to be attached to the map + */ + public function addEvent(EGMapEvent $event) + { + if (null === $this->resources->itemAt('events')) + $this->resources->add('events', new CTypedList('EGMapEvent')); + + $this->resources->itemAt('events')->add($event); + } + + /** + * $directions getter + * + * @return array $directions + * @author Vincent Guillon + * @since 2009-11-13 17:18:29 + */ + public function getDirections() + { + + return $this->resources->itemAt('directions'); + } + + /** + * $directions setter + * + * @param CTypedList $directions + * @author Vincent Guillon + * @since 2009-11-13 17:21:18 + */ + public function setDirections($directions = null) + { + + if ($directions instanceof CTypedList) + $this->resources->add('directions', $directions); + } + + /** + * Add direction to list ($this->directions) + * + * @param EGMapDirection $directions + * @author Antonio Ramirez + */ + public function addDirection(EGMapDirection $direction) + { + if (null === $this->resources->itemAt('directions')) + $this->resources->add('directions', new CTypedList('EGMapDirection')); + + $this->resources->itemAt('directions')->add($direction); + } + + /** + * Returns the javascript string which defines the markers + * @return string + * @since 2011-01-22 modified Antonio Ramirez + * Added support for marker clusterer + */ + public function getMarkersJs() + { + $return = ''; + if (null !== $this->resources->itemAt('markers')) + { + foreach ($this->resources->itemAt('markers') as $marker) + { + $return .= $marker->toJs($this->getJsName()); + if (null !== $this->_markerClusterer) + $this->_markerClusterer->addMarker($marker); + $return .= "\n "; + } + } + return $return; + } + + /** + * Returns the javascript string which defines events linked to the map + * + * @return string + * @since 2011-01-21 handles different type of events now + */ + public function getEventsJs() + { + + $return = ''; + if (null !== $this->resources->itemAt('events')) + { + foreach ($this->resources->itemAt('events') as $event) + { + $return .= $event->toJs($this->getJsName()); + $return .= "\n"; + } + } + return $return; + } + + /** + * Returns the javascript string which defines the polygons + * @return string + * @since 2011-03-10 Matt Kay + * Added function based on getMarkersJs + */ + public function getPolygonsJs() + { + $return = ''; + if (null !== $this->resources->itemAt('polygons')) + { + foreach ($this->resources->itemAt('polygons') as $polygon) + { + $return .= $polygon->toJs($this->getJsName()); + $return .= "\n "; + } + } + return $return; + } + + /** + * Returns the javascript string which defines the circles + * @return string + * @since 2011-03-23 Antonio Ramirez + * + */ + public function getCirclesJs() + { + $return = ''; + if (null !== $this->resources->itemAt('circles')) + { + foreach ($this->resources->itemAt('circles') as $circle) + { + $return .= $circle->toJs($this->getJsName()); + $return .= "\n "; + } + } + return $return; + } + + /** + * Returns the javascript string which defines rectangles + * @return string + * @since 2011-03-23 Antonio Ramirez + * + */ + public function getRectanglesJs() + { + $return = ''; + if (null !== $this->resources->itemAt('rectangles')) + { + foreach ($this->resources->itemAt('rectangles') as $rectangle) + { + $return .= $rectangle->toJs($this->getJsName()); + $return .= "\n "; + } + } + return $return; + } + + /** + * Get the directions javascript code + * + * @return string $js_code + * @author Antonio Ramirez + */ + public function getDirectionsJs() + { + $js_code = ''; + if (null !== $this->resources->itemAt('directions')) + { + foreach ($this->resources->itemAt('directions') as $direction) + { + $js_code .= $direction->toJs($this->getJsName()); + $js_code .= "\n "; + } + } + return $js_code; + } + + /** + * + * Adds global variables to be set before init function + * @param string $name + * @param mixed $value + */ + public function addGlobalVariable($name, $value='null') + { + if (null === $this->resources->itemAt('variables')) + $this->resources->add('variables', new CMap()); + + $this->resources->itemAt('variables')->add($name, $value); + } + + /** + * + * @return global variable if set + */ + public function getGlobalVariable($name) + { + if (null === $this->resources->itemAt('variables')) + return null; + + return $this->resources->itemAt('variables')->itemAt($name); + } + + /** + * + * Removes a global variable + * @param string $name of the variable to remove + */ + public function removeGlobalVariable($name) + { + if (null === $this->resources->itemAt('variables')) + return; + + $this->resources->itemAt('variables')->remove($name); + } + + /** + * + * @return string global variables in JS format + */ + public function getGlobalVariables() + { + $return = ''; + if (null !== $this->resources->itemAt('variables')) + { + foreach ($this->resources->itemAt('variables') as $name => $value) + { + $return .=' + var ' . $name . ' = ' . $value . ';'; + } + } + return $return; + } + + /** + * Defines one style of the div container + * @param string $style_tag name of css tag + * @param string $style_value value of css tag + * @since 2010-12-22 modified for Yii Antonio Ramirez + */ + public function setContainerStyle($style_tag, $style_value) + { + if (!is_array($this->_styleOptions)) + $this->_styleOptions = array(); + + $this->_styleOptions = array_merge($this->_styleOptions, array($style_tag => $style_value)); + } + + /** + * + * Gets one style of the Google Map div + * @param string $style_tag name of css tag + * @since 2010-12-22 modified Antonio Ramirez + */ + public function getContainerStyle($style_tag) + { + if (isset($this->_styleOptions[$style_tag])) + return $this->_styleOptions[$style_tag]; + return false; + } + + /** + * Sets the center of the map at the beginning + * + * @param float $lat + * @param float $lng + * @since 2010-12-22 modified for Yii Antonio Ramirez + */ + public function setCenter($lat=null, $lng=null) + { + $coord = new EGMapCoord($lat, $lng); + $this->options['center'] = $coord; + } + + /** + * + * @return EGMapCoord + */ + public function getCenterCoord() + { + return $this->options['center']; + } + + /** + * + * @return float Latitude + */ + public function getCenterLat() + { + + return isset($this->options['center']) ? $this->getCenterCoord()->getLatitude() : null; + } + + /** + * + * @return float Longitude + */ + public function getCenterLng() + { + return isset($this->options['center']) ? $this->getCenterCoord()->getLongitude() : null; + } + + /** + * gets the width of the map in pixels according to container style + * @return integer + * @since 2010-12-22 code reduction Yii Antonio Ramirez + */ + public function getWidth() + { + if (substr($this->getContainerStyle('width'), -2, 2) != 'px') + return false; + return intval(substr($this->getContainerStyle('width'), 0, -2)); + } + + /** + * gets the width of the map in pixels according to container style + * @return integer + * @since 2010-12-22 code reduction Antonio Ramirez + */ + public function getHeight() + { + if (substr($this->getContainerStyle('height'), -2, 2) != 'px') + return false; + + return intval(substr($this->getContainerStyle('height'), 0, -2)); + } + + /** + * sets the width of the map in pixels + * + * @param integer | string + */ + public function setWidth($width) + { + if (is_numeric($width)) + { + $width = $width . 'px'; + } + $this->setContainerStyle('width', $width); + } + + /** + * sets the width of the map in pixels + * + * @param integer | string + */ + public function setHeight($height) + { + if (is_numeric($height)) + { + $height = $height . 'px'; + } + $this->setContainerStyle('height', $height); + } + + /** + * Returns the URL of a static version of the map (when JavaScript is not active) + * Supports only markers and basic parameters: center, zoom, size. + * @param string $map_type = 'mobile' + * @param string $hl Language (fr, en...) + * @return string URL of the image + * @author Laurent Bachelier + * @since 2010-12-22 inserted http_build_query modified Antonio Ramirez + */ + public function getStaticMapUrl($maptype='mobile', $hl='es') + { + $params = array( + 'maptype' => $maptype, + 'zoom' => $this->getZoom(), + 'key' => $this->getAPIKey(), + 'center' => $this->getCenterLat() . ',' . $this->getCenterLng(), + 'size' => $this->getWidth() . 'x' . $this->getHeight(), + 'hl' => $hl, + 'markers' => $this->getMarkersStatic() + ); + $pairs = array(); + + $params = http_build_query($params); + + return 'http://maps.google.com/staticmap?' . $params; //implode('&',$pairs); + } + + /** + * Returns the static code to create markers + * @return string + * @author Laurent Bachelier + * @since 2010-12-22 Yii modified Antonio Ramirez + */ + protected function getMarkersStatic() + { + $markers_code = array(); + if (null !== $this->resources->itemAt('markers')) + { + foreach ($this->resources->itemAt('markers') as $marker) + { + $markers_code[] = $marker->getMarkerStatic(); + } + } + return implode('|', $markers_code); + } + + /** + * + * calculates the center of the markers linked to the map + * + * @return EGMapCoord + * @since 2010-12-22 modified for Yii Antonio Ramirez + */ + public function getMarkersCenterCoord() + { + if (null === $this->resources->itemAt('markers')) + throw new CException(Yii::t('EGMap', 'At least one more marker is necessary for getMarkersCenterCoord to work')); + //todo: check for markers existence + return EGMapMarker::getCenterCoord($this->resources->itemAt('markers')); + } + + /** + * sets the center of the map at the center of the markers + * @since 2010-12-22 modified for Yii Antonio Ramirez + */ + public function centerOnMarkers() + { + $center = $this->getMarkersCenterCoord(); + + $this->setCenter($center->getLatitude(), $center->getLongitude()); + } + + /** + * + * calculates the zoom which fits the markers on the map + * + * @param integer $margin a scaling factor around the smallest bound + * @return integer $zoom + * @author fabriceb + * @since 2009-05-02 + * @since 2010-12-22 modified for Yii Antonio Ramirez + */ + public function getMarkersFittingZoom($margin = 0, $default_zoom = 14) + { + if (null === $this->resources->itemAt('markers')) + throw new CException(Yii::t('EGMap', 'At least one more marker is necessary for getMarkersFittingZoom to work')); + //todo check for markers existence + $bounds = EGMapBounds::getBoundsContainingMarkers($this->resources->itemAt('markers'), $margin); + + return $bounds->getZoom(min($this->getWidth(), $this->getHeight()), $default_zoom); + } + + /** + * sets the zoom of the map to fit the markers (uses mercator projection to guess the size in pixels of the bounds) + * WARNING : this depends on the width in pixels of the resulting map + * + * @param integer $margin a scaling factor around the smallest bound + * @author fabriceb + * @since 2009-05-02 + */ + public function zoomOnMarkers($margin = 0, $default_zoom = 14) + { + $this->options['zoom'] = $this->getMarkersFittingZoom($margin, $default_zoom); + } + + /** + * sets the zoom and center of the map to fit the markers (uses mercator projection to guess the size in pixels of the bounds) + * + * @param integer $margin a scaling factor around the smallest bound + * @author fabriceb + * @since 2009-05-02 + */ + public function centerAndZoomOnMarkers($margin = 0, $default_zoom = 14) + { + $this->centerOnMarkers(); + $this->zoomOnMarkers($margin, $default_zoom); + } + + /** + * + * @return EGMapBounds + * @author fabriceb + * @since Jun 2, 2009 fabriceb + * @since 2010-12-22 modified for Yii Antonio Ramirez + */ + public function getBoundsFromCenterAndZoom() + { + return EGMapBounds::getBoundsFromCenterAndZoom($this->getCenterCoord(), $this->zoom, $this->getWidth(), $this->getHeight()); + } + + /** + * backwards compatibility + * @param string[] $api_keys + * @return string + * @author fabriceb + * @since Jun 17, 2009 fabriceb + * @since 2010-12-22 modified for Yii Antonio Ramirez + */ + public static function guessAPIKey($api_keys = null) + { + return EGMapClient::guessAPIKey($api_keys); + } + + /** + * + * Loops through the plugins and registers its required + * assets + * @author Antonio Ramirez + */ + private function registerPlugins() + { + $assetDir = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'assets' . DIRECTORY_SEPARATOR; + $assetUrl = Yii::app()->assetManager->publish($assetDir); + + + $cs = Yii::app()->getClientScript(); + + foreach ($this->plugins as $p) + { + + if ($p['flag']) + { + foreach ($p['js'] as $js) + $cs->registerScriptFile($assetUrl . "/" . $js, CClientScript::POS_END); + } + } + } + + /** + * + * Flags a plugin to register its assets + * @param string $plugin name + * @param boolean $register + */ + private function registerPlugin($plugin, $register=true) + { + $this->plugins[$plugin]["flag"] = $register; + } + + /** + * + * Checks whether a plugin has been flagged to be + * registered or not + * @param string $plugin name + * @return boolean true|false + */ + private function pluginRegistered($plugin) + { + return $this->plugins[$plugin]["flag"]; + } + + /** + * + * Encodes an option array into + * appropiate Javascript object + * representation + * @param mixed $value + * @author Antonio Ramirez + */ + public static function encode($value) + { + + if (is_string($value)) + { + if (strpos($value, 'js:') === 0) + return substr($value, 3); + else + return $value; + } + else if ($value === null) + return 'null'; + else if (is_bool($value)) + return $value ? 'true' : 'false'; + else if (is_integer($value)) + return "$value"; + else if (is_float($value)) + { + if ($value === -INF) + return 'Number.NEGATIVE_INFINITY'; + else if ($value === INF) + return 'Number.POSITIVE_INFINITY'; + else + return rtrim(sprintf('%.16F', $value), '0'); // locale-independent representation + } + else if (is_object($value)) + { + if (method_exists($value, 'toJs')) + return $value->toJs(); + return self::encode(get_object_vars($value)); + } + else if (is_array($value)) + { + $es = array(); + if (($n = count($value)) > 0 && array_keys($value) !== range(0, $n - 1)) + { + + foreach ($value as $k => $v) + { + if (null === $v) + continue; + $es[] = $k . ":" . self::encode($v); + } + + return '{' . implode(',' . PHP_EOL, $es) . '}'; + } + else + { + foreach ($value as $v) + $es[] = self::encode($v); + return '[' . implode(',', $es) . ']'; + } + } + else + return ''; + } + +} diff --git a/protected/extensions/egmap/EGMapApiKeyList.php b/protected/extensions/egmap/EGMapApiKeyList.php new file mode 100644 index 0000000..b6fbfb5 --- /dev/null +++ b/protected/extensions/egmap/EGMapApiKeyList.php @@ -0,0 +1,98 @@ +<?php +/** + * + * EGMapApiKeyList Class + * + * Collection of Google API Keys + * + * @author Antonio Ramirez Cobos + * @link www.ramirezcobos.com + * + * + * @copyright + * + * Copyright (c) 2010 Antonio Ramirez Cobos + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +class EGMapApiKeyList { + + /** + * + * default API key (localhost) + * @var string API key + */ + private $_default = 'ABQIAAAAiNlS-KWUYtfPmXrWytgMmxT2yXp_ZAY8_ufC3CFXhHIE1NvwkxQlQzG8ekt6PEzv6dL5UtfryHSg8g'; + /** + * + * Holds the collection of keys + * @var CMap + */ + private $_keys = null; + /** + * + * Class constructor + * @param string $domain + * @param string $key + */ + public function __construct( $domain=null, $key=null ) + { + // set default API key + $this->addAPIKey( 'localhost', $this->_default ); + + if( $domain != null && $key != null ) + $this->add( $domain, $key ); + } + /** + * + * Adds a Google API key to collection + * @param string $domain + * @param string $key + */ + public function addAPIKey( $domain , $key ){ + if( null === $this->_keys ) + $this->_keys = new CMap(); + + $this->_keys->add( $domain, $key ); + } + /** + * + * Returns Google API key if found in collection + * @param string $domain + * @return string Google API key + */ + public function getAPIKeyByDomain( $domain ) + { + if( !$this->_keys->contains( $domain ) ) + return false; + return $this->_keys->itemAt( $domain ); + } + /** + * Returns and google api key by domain name discovery + * @return Google API key + */ + public static function guessAPIKey( ) + { + if (isset($_SERVER['SERVER_NAME'])) + { + return $this->getAPIKeyByDomain( $_SERVER['SERVER_NAME'] ); + } + else if (isset($_SERVER['HTTP_HOST'])) + { + return $this->getAPIKeyByDomain( $_SERVER['HTTP_HOST'] ); + } + return $this->getAPIKeyByDomain('localhost'); + } +}
\ No newline at end of file diff --git a/protected/extensions/egmap/EGMapBase.php b/protected/extensions/egmap/EGMapBase.php new file mode 100644 index 0000000..bedd417 --- /dev/null +++ b/protected/extensions/egmap/EGMapBase.php @@ -0,0 +1,134 @@ +<?php + +class EGMapBase { + + protected static $_counter = 0; + protected $js_name; + protected $options = array(); + + /** + * + * Sets value of a component property. + * Do not call this method. This is a PHP magic method that we override + * to allow using the following syntax to set a property or attach setProperty method + * to create appropiate setting to specific properties + * <pre> + * $this->propertyName=$value; + * $this->setName($value) + * </pre> + * @param string $name the property name + * @param mixed $value + */ + public function __set($name, $value) + { + $setter = 'set' . $name; + if (method_exists($this, $setter)) + return $this->$setter($value); + elseif (array_key_exists($name, $this->options)) + { + return $this->options[$name] = $value; + } + if (method_exists($this, 'get' . $name)) + throw new CException(Yii::t('EGMap', 'Property "{class}.{property}" is read only.', array('{class}' => get_class($this), '{property}' => $name))); + else + throw new CException(Yii::t('EGMap', 'Property "{class}.{property}" is not defined.', array('{class}' => get_class($this), '{property}' => $name))); + } + + /** + * + * Returns a property value, an event handler list or a behavior based on its name. + * Do not call this method. This is a PHP magic method that we override + * to allow using the following syntax to read a property + * <pre> + * $value=$component->propertyName; + * $value=$component->getPropertyName; + * </pre> + * @param string $name + * @throws CException + */ + public function __get($name) + { + $getter = 'get' . ucfirst($name); + + if (method_exists($this, $getter)) + return $this->$getter(); + if (array_key_exists($name, $this->options)) + { + return $this->options[$name]; + } + + throw new CException(Yii::t('EGMap', 'Property "{class}.{property}" is not defined.', array('{class}' => get_class($this), '{property}' => $name))); + } + + /** + * Checks if a property value is null. + * Do not call this method. This is a PHP magic method that we override + * to allow using isset() to detect if a component property is set or not. + * + * @param string $name name of the property + */ + public function __isset($name) + { + $getter = 'get' . ucfirst($name); + if (method_exists($this, $getter)) + return $this->$getter() !== null; + + return isset($this->options[$name]); + } + + /** + * Sets a component property to be null. + * Do not call this method. This is a PHP magic method that we override + * to allow using unset() to set a component property to be null. + * @param string $name the property name or the event name + * @throws CException if the property is read only or not exists. + */ + public function __unset($name) + { + $setter = 'set' . $name; + if (method_exists($this, $setter)) + return $this->$setter(null); + else if (isset($this->option[$name])) + return $this->option[$name] = null; + else if (method_exists($this, 'get' . $name)) + throw new CException(Yii::t('EGMap', 'Property "{class}.{property}" is read only.', array('{class}' => get_class($this), '{property}' => $name))); + else + throw new CException(Yii::t('EGMap', 'Property "{class}.{property}" is not defined.', array('{class}' => get_class($this), '{property}' => $name))); + } + + /** + * @return string Javascript name of the renderer service + * @author Antonio Ramirez + * @since 2011-01-24 + */ + public function getJsName($autoGenerate=true) + { + if ($this->js_name !== null) + return $this->js_name; + else if ($autoGenerate) + return $this->js_name = get_class($this) . self::$_counter++; + } + + /** + * + * Sets the Javascript name of the renderer service + * @param string $name + */ + public function setJsName($name) + { + + $this->js_name = $name; + } + + /** + * @return array $options + * @author Antonio Ramirez + * @since 2011-01-25 + */ + public function getOptions() + { + return $this->options; + } + +} + diff --git a/protected/extensions/egmap/EGMapBounds.php b/protected/extensions/egmap/EGMapBounds.php new file mode 100644 index 0000000..befdfc7 --- /dev/null +++ b/protected/extensions/egmap/EGMapBounds.php @@ -0,0 +1,469 @@ +<?php + +/** + * + * EGMapBounds Class + * Modified by Antonio Ramirez Cobos + * for Yii to integrate class as Extension + * + * @since 2010-12-22 Antonio Ramirez + * @link http://www.ramirezcobos.com + * + * GoogleMap Bounds + * @author Fabrice Bernhard + * + * @copyright + * info as this library is a modified version of Fabrice Bernhard + * + * Copyright (c) 2008 Fabrice Bernhard + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +class EGMapBounds { + + /** + * + * South West EGMapCoord + * @var EGMapCoord + */ + protected $sw = null; + + /** + * + * North East EGMapCoord + * @var EGMapCoord + */ + protected $ne = null; + + /** + * Create a new Bounds object + * + * @param EGMapCoord $nw + * @param EGMapCoord $se + */ + public function __construct(EGMapCoord $sw = null, EGMapCoord $ne = null) + { + if (is_null($sw)) + { + $sw = new EGMapCoord(); + } + if (is_null($ne)) + { + $ne = new EGMapCoord(); + } + $this->sw = $sw; + $this->ne = $ne; + } + + /** + * + * @return EGMapCoord object + */ + public function getNorthEast() + { + + return $this->ne; + } + + /** + * + * @return EGMapCoord object + */ + public function getSouthWest() + { + return $this->sw; + } + + /** + * + * Creates EGMapCoords (bounds) from a string representation + * of Lat,Lon values + * @param string $string ((48.82415805606007,%202.308330535888672),%20(48.867086142850226,%202.376995086669922)) + */ + static public function createFromString($string) + { + preg_match('/\(\((.*?)\), \((.*?)\)\)/', $string, $matches); + if (count($matches) == 3) + { + $sw = EGMapCoord::createFromString($matches[1]); + $ne = EGMapCoord::createFromString($matches[2]); + if (!is_null($sw) && !is_null($ne)) + { + + return new EGMapBounds($sw, $ne); + } + + return null; + } + } + + /** + * Google String representations + * + * @return string + * @author fabriceb + * @since Feb 17, 2009 fabriceb + */ + public function __toString() + { + + return '((' . $this->getSouthWest()->getLatitude() . ', ' . $this->getSouthWest()->getLongitude() . '), (' . $this->getNorthEast()->getLatitude() . ', ' . $this->getNorthEast()->getLongitude() . '))'; + } + + /** + * + * @return string LatLngBounds constructor + */ + public function toJs() + { + return 'new google.maps.LatLngBounds('.$this->getSouthWest()->toJs().','.$this->getNorthEast()->toJs().')'; + } + + /** + * Get the latitude of the center of the zone + * + * @return integer + * @author fabriceb + * @since 2008-12-03 + */ + public function getCenterLat() + { + if (is_null($this->getSouthWest()) || is_null($this->getNorthEast())) + { + + return null; + } + + return floatval(($this->getSouthWest()->getLatitude() + $this->getNorthEast()->getLatitude()) / 2); + } + + /** + * Get the longitude of the center of the zone + * + * @return integer + * @author fabriceb + * @since 2008-12-03 + */ + public function getCenterLng() + { + if (is_null($this->getSouthWest()) || is_null($this->getNorthEast())) + { + + return null; + } + + return floatval(($this->getSouthWest()->getLongitude() + $this->getNorthEast()->getLongitude()) / 2); + } + + /** + * Get the coordinates of the center of the zone + * + * @return EGMapCoord + * @author fabriceb + * @since 2008-12-03 + */ + public function getCenterCoord() + { + + return new EGMapCoord($this->getCenterLat(), $this->getCenterLng()); + } + + /** + * Hauteur du carré + * + * @return float + * @author fabriceb + * @since Feb 17, 2009 fabriceb + */ + public function getHeight() + { + + return abs($this->getNorthEast()->getLatitude() - $this->getSouthWest()->getLatitude()); + } + + /** + * Largeur du carré + * + * @return float + * @author fabriceb + * @since Feb 17, 2009 fabriceb + */ + public function getWidth() + { + + return abs($this->getNorthEast()->getLongitude() - $this->getSouthWest()->getLongitude()); + } + + /** + * Does a homthety transformtion on the bounds, centered on the center of the bounds + * + * @param float $factor + * @return EGMapBounds $bounds + * @author fabriceb + * @since Feb 17, 2009 fabriceb + */ + public function getHomothety($factor) + { + $bounds = new EGMapBounds(); + $lat = $this->getCenterLat(); + $lng = $this->getCenterLng(); + $bounds->getNorthEast()->setLatitude($factor * $this->getNorthEast()->getLatitude() + $lat * (1 - $factor)); + $bounds->getSouthWest()->setLatitude($factor * $this->getSouthWest()->getLatitude() + $lat * (1 - $factor)); + $bounds->getNorthEast()->setLongitude($factor * $this->getNorthEast()->getLongitude() + $lng * (1 - $factor)); + $bounds->getSouthWest()->setLongitude($factor * $this->getSouthWest()->getLongitude() + $lng * (1 - $factor)); + + return $bounds; + } + + /** + * gets zoomed out bounds + * + * @param integer $zoom_coef + * @return EGMapBounds + * @author fabriceb + * @since Feb 18, 2009 fabriceb + */ + public function getZoomOut($zoom_coef) + { + if ($zoom_coef > 0) + { + $bounds = $this->getHomothety(pow(2, $zoom_coef)); + + return $bounds; + } + + return $this; + } + + /** + * Returns the most appropriate zoom to see the bounds on a map with min(width,height) = $min_w_h + * + * @param integer $min_w_h width or height of the map in pixels + * @return integer + * @author fabriceb + * @since Feb 18, 2009 fabriceb + */ + public function getZoom($min_w_h, $default_zoom = 14) + { + $infinity = 999999999; + $factor_h = $infinity; + $factor_w = $infinity; + + /* + + formula: the width of the bounds in "pixels" is pix_w * 2^z + We want pix_w * 2^z to fit in min_w_h so we are looking for + z = round ( log2 ( min_w_h / pix_w ) ) + */ + + $sw_lat_pix = EGMapCoord::fromLatToPix($this->getSouthWest()->getLatitude(), 0); + $ne_lat_pix = EGMapCoord::fromLatToPix($this->getNorthEast()->getLatitude(), 0); + $pix_h = abs($sw_lat_pix - $ne_lat_pix); + if ($pix_h > 0) + { + $factor_h = $min_w_h / $pix_h; + } + + $sw_lng_pix = EGMapCoord::fromLngToPix($this->getSouthWest()->getLongitude(), 0); + $ne_lng_pix = EGMapCoord::fromLngToPix($this->getNorthEast()->getLongitude(), 0); + $pix_w = abs($sw_lng_pix - $ne_lng_pix); + if ($pix_w > 0) + { + $factor_w = $min_w_h / $pix_w; + } + + $factor = min($factor_w, $factor_h); + + // bounds is one point, no zoom can be determined + if ($factor == $infinity) + { + + return $default_zoom; + } + + return round(log($factor, 2)); + } + + /** + * + * Returns the boundaries that the others have + * + * @param EGMapBounds[] $boundss + * @param float $margin + * @return EGMapBounds + * @author fabriceb + * @since Feb 18, 2009 fabriceb + */ + public static function getBoundsContainingAllBounds($boundss, $margin = 0) + { + $min_lat = 1000; + $max_lat = -1000; + $min_lng = 1000; + $max_lng = -1000; + foreach ($boundss as $bounds) + { + $min_lat = min($min_lat, $bounds->getSouthWest()->getLatitude()); + $min_lng = min($min_lng, $bounds->getSouthWest()->getLongitude()); + $max_lat = max($max_lat, $bounds->getNorthEast()->getLatitude()); + $max_lng = max($max_lng, $bounds->getNorthEast()->getLongitude()); + } + + if ($margin > 0) + { + $min_lat = $min_lat - $margin * ($max_lat - $min_lat); + $min_lng = $min_lng - $margin * ($max_lng - $min_lng); + $max_lat = $max_lat + $margin * ($max_lat - $min_lat); + $max_lng = $max_lng + $margin * ($max_lng - $min_lng); + } + + $bounds = new EGMapBounds(new EGMapCoord($min_lat, $min_lng), new EGMapCoord($max_lat, $max_lng)); + return $bounds; + } + + /** + * Retuns bounds containg an array of coordinates + * + * @param EGMapCoord[] $coords + * @param float $margin + * @return EGMapBounds + * @author fabriceb + * @since Mar 13, 2009 fabriceb + */ + public static function getBoundsContainingCoords($coords, $margin = 0) + { + $min_lat = 1000; + $max_lat = -1000; + $min_lng = 1000; + $max_lng = -1000; + foreach ($coords as $coord) + { + /* @var $coord EGMapCoord */ + $min_lat = min($min_lat, $coord->getLatitude()); + $max_lat = max($max_lat, $coord->getLatitude()); + $min_lng = min($min_lng, $coord->getLongitude()); + $max_lng = max($max_lng, $coord->getLongitude()); + } + + if ($margin > 0) + { + $min_lat = $min_lat - $margin * ($max_lat - $min_lat); + $min_lng = $min_lng - $margin * ($max_lng - $min_lng); + $max_lat = $max_lat + $margin * ($max_lat - $min_lat); + $max_lng = $max_lng + $margin * ($max_lng - $min_lng); + } + $bounds = new EGMapBounds(new EGMapCoord($min_lat, $min_lng), new EGMapCoord($max_lat, $max_lng)); + + return $bounds; + } + + /** + * + * @param GMapMarker[] $markers array of Markers + * @param float $margin margin factor for the bounds + * @return EGMapBounds + * @author fabriceb + * @since 2009-05-02 + * @since 2011-01-25 modified by Antonio Ramirez + * + * */ + public static function getBoundsContainingMarkers($markers, $margin = 0) + { + $coords = array(); + foreach ($markers as $marker) + { + array_push($coords, $marker->position); + } + + return EGMapBounds::getBoundsContainingCoords($coords, $margin); + } + + /** + * + * @param GMapPolygon[] $polygons array of Polygons + * @param float $margin margin factor for the bounds + * @return EGMapBounds + * @author Matt Kay + * @since 2011-03-10 + * Added this function based on getBoundsContainingMarkers + * + * */ + public static function getBoundsContainingPolygons($polygons, $margin = 0) + { + $coords = array(); + foreach ($polygons as $polygon) + { + // merge LatLng arrays + array_merge($coords, $polygon->getCoords()); + } + + return EGMapBounds::getBoundsContainingCoords($polygon->getCoords(), $margin); + } + + /** + * Calculate the bounds corresponding to a specific center and zoom level for a give map size in pixels + * + * @param EGMapCoord $center_coord + * @param integer $zoom + * @param integer $width + * @param integer $height + * @return EGMapBounds + * @author fabriceb + * @since Jun 2, 2009 fabriceb + */ + public static function getBoundsFromCenterAndZoom(EGMapCoord $center_coord, $zoom, $width, $height = null) + { + if (is_null($height)) + { + $height = $width; + } + + $center_lat = $center_coord->getLatitude(); + $center_lng = $center_coord->getLongitude(); + + $pix = EGMapCoord::fromLatToPix($center_lat, $zoom); + $ne_lat = EGMapCoord::fromPixToLat($pix - round(($height - 1) / 2), $zoom); + $sw_lat = EGMapCoord::fromPixToLat($pix + round(($height - 1) / 2), $zoom); + + $pix = EGMapCoord::fromLngToPix($center_lng, $zoom); + $sw_lng = EGMapCoord::fromPixToLng($pix - round(($width - 1) / 2), $zoom); + $ne_lng = EGMapCoord::fromPixToLng($pix + round(($width - 1) / 2), $zoom); + + return new EGMapBounds(new EGMapCoord($sw_lat, $sw_lng), new EGMapCoord($ne_lat, $ne_lng)); + } + + /** + * + * @param EGMapCoord $gmap_coord + * @return boolean $is_inside + * @author fabriceb + * @since Jun 2, 2009 fabriceb + */ + public function containsEGMapCoord(EGMapCoord $gmap_coord) + { + $is_inside = + ( + $gmap_coord->getLatitude() < $this->getNorthEast()->getLatitude() + && + $gmap_coord->getLatitude() > $this->getSouthWest()->getLatitude() + && + $gmap_coord->getLongitude() < $this->getNorthEast()->getLongitude() + && + $gmap_coord->getLongitude() > $this->getSouthWest()->getLongitude() + ); + + return $is_inside; + } + +} diff --git a/protected/extensions/egmap/EGMapCircle.php b/protected/extensions/egmap/EGMapCircle.php new file mode 100644 index 0000000..d3f8e0c --- /dev/null +++ b/protected/extensions/egmap/EGMapCircle.php @@ -0,0 +1,242 @@ +<?php + +/** + * + * EGMapCircle + * A GoogleMap Circle + * + * @author Antonio Ramirez Cobos + * + * Example: + * + * $circle = new EGMapCircle(new EGMapCoord(34.04924594193164, -118.24104309082031)); + * $circle->radius = 300000; + * $circle->addHtmlInfoWindow(new EGMapInfoWindow('Hey! I am a circlel!')); + * $gMap->addCircle($circle); + * + * @copyright + * + * Copyright (c) 2011 Antonio Ramirez + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +class EGMapCircle extends EGMapBase { + + protected $options = array( + 'center' => null, // EGMapCoord + // Indicates whether this Circle handles click events. Defaults to true. + 'clickable' => true, + // Map on which to display Circle. + 'map' => null, + // coordinates of the polygon + 'radius' => null, + // stroke color of the edge of the circle + 'strokeColor' => '"#FF0000"', + //stroke opacity of the edge of the circle + 'strokeOpacity' => 0.8, + //stroke weight of the edge of the circle + 'strokeWeight' => 2, + //fill color of the polygon + 'fillColor' => '"#FF0000"', + //fill opacity of the circle + 'fillOpacity' => 0.35 + ); + + /** + * + * Info window object attached to the object + * @var EGMapInfoWindow + */ + protected $info_window = null; + + /** + * + * If the Info window is shared or not + * @var boolean + */ + protected $info_window_shared = false; + + /** + * + * Events attached to the object + * @var array + */ + protected $events = null; + + /** + * + * google maps js object name + * @var string + */ + protected $circle_object = 'google.maps.Circle'; + + /** + * + * @param EGMapCoord center coordinates of the circle + * @param string $js_name name of the circle variable + * @param array $options of the circle + * @param EGmapEvent[] array of GoogleMap Events linked to the circle + * @author Antonio Ramirez + */ + public function __construct(EGMapCoord $center, $options = array(), $js_name='circle', $events=array()) + { + if ($js_name !== 'circle') + $this->setJsName($js_name); + + $this->setOptions($options); + + $this->setCenter($center); + + $this->events = new CTypedList('EGMapEvent'); + + $this->setEvents($events); + } + + /** + * + * Batch set events by an array of EGMapEvents + * @param array $events + */ + public function setEvents($events) + { + if (!is_array($events)) + throw new CException(Yii::t('EGMap', 'Parameter of "{class}.{method}" {e}.', array('{class}' => get_class($this), '{method}' => 'setEvents', '{e}' => 'must be of type array'))); + if (null === $this->events) + $this->events = new CTypedList('EGMapEvent'); + + foreach ($events as $e) + { + $this->events->add($e); + } + } + + /** + * Adds an event listener to the marker + * + * @param EGMapEvent $event + */ + public function addEvent(EGMapEvent $event) + { + $this->events->add($event); + } + + /** + * @param array $options + * @author Antonio Ramirez + */ + public function setOptions($options) + { + + $this->options = array_merge($this->options, $options); + } + + /** + * gets the center coordinates of the circle + * + * @return EGMapCoord $center + * @author Antonio Ramirez + */ + public function getCenter() + { + return $this->options['center']; + } + + /** + * sets the coordinates of the circle + * + * @param EGMapCoord $center + * @author Antonio Ramirez Cobos + */ + public function setCenter(EGMapCoord $center) + { + $this->options['center'] = $center; + } + + /** + * @param string $map_js_name + * @return string Javascript code to create the circle + * @author Antonio Ramirez + */ + public function toJs($map_js_name = 'map') + { + $this->options['map'] = $map_js_name; + + $return = ''; + if (null !== $this->info_window) + { + if ($this->info_window_shared) + { + $info_window_name = $map_js_name . '_info_window'; + $this->addEvent( + new EGMapEvent( + 'click', + 'if (' . $info_window_name . ') ' . $info_window_name . '.close();' . PHP_EOL . + $info_window_name . ' = ' . $this->info_window->getJsName() . ';' . PHP_EOL . + $info_window_name . ".setPosition(" . $this->getJsName() . ".getCenter());" . PHP_EOL . + $info_window_name . ".open(" . $map_js_name . ");" . PHP_EOL + )); + } + else + $this->addEvent(new EGMapEvent('click', + $this->info_window->getJsName() . ".setPosition(" . $this->getJsName() . ".getCenter());" . PHP_EOL . + $this->info_window->getJsName() . ".open(" . $map_js_name . ");" . PHP_EOL + )); + $return .= $this->info_window->toJs(); + } + + $return .='var ' . $this->getJsName() . ' = new ' . $this->circle_object . '(' . EGMap::encode($this->options) . ');' . PHP_EOL; + + foreach ($this->events as $event) + { + $return .= $event->getEventJs($this->getJsName()) . PHP_EOL; + } + + return $return; + } + + /** + * Adds an onlick listener that open a html window with some text + * + * @param EGMapInfoWindow $info_window + * @param boolean $shared among other markers (unique info_window display) + * + * @author Antonio Ramirez + * @since 2011-01-23 Added shared functionality for infoWindows + */ + public function addHtmlInfoWindow(EGMapInfoWindow $info_window, $shared = true) + { + $this->info_window = $info_window; + $this->info_window_shared = $shared; + } + + /** + * + * @return boolean if info window is shared or not + */ + public function htmlInfoWindowShared() + { + return $this->info_window_shared; + } + + /** + * @return EGMapInfoWindow + * @author Antonio Ramirez + */ + public function getHtmlInfoWindow() + { + return $this->info_window; + } + +} diff --git a/protected/extensions/egmap/EGMapClient.php b/protected/extensions/egmap/EGMapClient.php new file mode 100644 index 0000000..34b56ba --- /dev/null +++ b/protected/extensions/egmap/EGMapClient.php @@ -0,0 +1,276 @@ +<?php + +/** + * + * EGMapClient Class + * A class to communicate with Google Maps + * Inspired on the work of Fabrice Bernhard + * + * @author Antonio Ramirez Cobos + * @link http://www.ramirezcobos.com + * + * @copyright + * info as this library is a modified version of Fabrice Bernhard + * + * Copyright (c) 2008 Fabrice Bernhard + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +class EGMapClient +{ + /** + * The URL for the RESTful geocode API. + * @since 2011-03-23 Matt Cheale Updated URL from v2 to v3 of the API. + * @since 2011-04-21 Matt Cheale Removed the format option so it can be customised in the geocoding methods. + * @since 2011-12-19 Antonio Ramirez renamed to make use of more APIs + */ + const API_GEOCODE_URL = 'http://maps.googleapis.com/maps/api/geocode/'; + /** + * The URL for the RESTful elevation API + */ + const API_ELEVATION_URL = 'http://maps.googleapis.com/maps/api/elevation/'; + + /** + * + * Constructor + * If $key parameter is set, it will try to add it + * to the collection. Array should be in the format of + * <pre> + * $gmapclient = new EGMapClient( array('domain'=>'googlekeyhere') ); + * </pre> + * @param array $key + * @since 2011-04-21 Matt Cheale $key parameter deprecated + */ + public function __construct($key = array()){} + + /** + * Sets the Google Maps API key + * @param string $key + * @deprecated + * @since 2011-04-21 Matt Cheale Deprecated as API Keys are no longer required. + */ + public function setAPIKey($domain, $key, $setAsDefault = false){} + + /** + * + * Sets default API key + * @param string $domain + * @deprecated + * @since 2011-04-21 Matt Cheale Deprecated as API Keys are no longer required. + */ + public function setDomain($domain){} + + /** + * Gets the Google Maps API key + * @return string $key + * @deprecated + * @since 2011-04-21 Matt Cheale Deprecated as API Keys are no longer required. + */ + public function getAPIKey($domain = null){} + + /** + * Guesses and sets default API Key + * @deprecated + * @since 2011-04-21 Matt Cheale Deprecated as API Keys are no longer required. + */ + protected function guessAndSetAPIKey($key){} + + /** + * Guesses the current domain + * @return string $domain + * @author Antonio Ramirez Cobos + * @deprecated + * @since 2011-04-21 Matt Cheale Deprecated as API Keys are no longer required. + */ + public static function guessDomain(){} + + /** + * Returns the collection of API keys + * @return CMap + * @deprecated + * @since 2011-04-21 Matt Cheale Deprecated as API Keys are no longer required. + */ + public function getAPIKeys() + { + return new CMap(); + } + + /** + * + * Sets the API keys collection + * @param CMap $api_keys + * @return false if $api_keys is not of class CMap + * @author Antonio Ramirez Cobos + * @deprecated + * @since 2011-04-21 Matt Cheale Deprecated as API Keys are no longer required. + */ + public function setAPIKeys($api_keys){} + + /** + * + * Changes default geocoding template + * Just in case google changes its API + * current is of default: {api}&output={format}&key={key}&q={address} + * @param string $template + * @author Antonio Ramirez Cobos + * @deprecated + * @since 2011-04-21 Matt Cheale Deprecated as latest code is not making any use of this. + */ + public function setGeoCodingTemplate($template){} + + /** + * + * Connection to Google Maps' API web service + * + * Modified to include a template for api + * just in case the url changes in future releases + * Includes template parsing and CURL calls + * @author Antonio Ramirez Cobos + * @since 2010-12-21 + * + * @param string $address + * @param string $format 'csv' or 'xml' or 'json' + * @return string + * @author fabriceb + * @since 2009-06-17 + * @since 2010-12-22 cUrl and Yii adaptation Antonio Ramirez + * @since 2011-04-21 Matt Cheale Updated to API V3 and moved HTTP call to another function. + * + */ + public function getGeocodingInfo($address, $format = 'json') + { + $apiURL = self::API_GEOCODE_URL . $format . '?address=' . urlencode($address) . '&sensor=false'; + return $this->callApi($apiURL); + } + + /** + * Reverse geocoding info + * + * @return string + * @author Vincent Guillon <vincentg@theodo.fr> + * @since 2010-03-04 + * @since 2010-12-22 modified by Antonio Ramirez (CUrl call) + * @since 2011-03-23 Matt Cheale Updated the query string to use v3 API variables. + * @since 2011-04-21 Matt Cheale Added format option and moved HTTP call to another function. + * @since 2011-12-19 Antonio Ramirez modified API call + */ + public function getReverseGeocodingInfo($lat, $lng, $format = 'json') + { + $apiURL = self::API_GEOCODE_URL . $format . '?latlng=' . $lat . ',' . $lng . '&sensor=false'; + return $this->callApi($apiURL); + } + /** + * Elevation info request + * + * @param string $locations the coordinates array to get elevation info from + * @param string $format 'xml' or 'json' + * @return string + * @author Antonio Ramirez + */ + public function getElevationInfo($locations, $format = 'json') + { + $apiURL = self::API_ELEVATION_URL . $format . '?locations=' . $locations . '&sensor=false'; + return $this->callApi($apiURL); + } + /** + * Takes the $apiURL and performs that HTTP request to Google, returning the + * raw data. + * + * @param string $apiURL + * @return string + * @author Matt Cheale + * @since 2011-04-21 + * @since 2011-12-17 Modified to fix open_basedir restrictions + */ + private function callApi($apiUrl) + { + if (function_exists('curl_version')) + { + $ch = curl_init(); + + curl_setopt($ch, CURLOPT_URL, $apiUrl); + curl_setopt($ch, CURLOPT_HEADER, 0); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER["HTTP_USER_AGENT"]); + $raw_data = $this->_curl_exec_follow($ch); + curl_close($ch); + } + else // no CUrl, try differently + $raw_data = file_get_contents($apiUrl); + + return $raw_data; + } + + /** + * This function handles redirections with CURL if safe_mode or open_basedir + * is enabled. + * @param resource $h the curl handle + * @param integer $maxredirections + */ + private function _curl_exec_follow(&$ch, $maxredirections = 5) + { + if (ini_get('open_basedir') == '' && ini_get('safe_mode') == 'Off') + { + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, $maxredirections > 0); + curl_setopt($ch, CURLOPT_MAXREDIRS, $maxredirections); + } else + { + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false); + if ($maxredirections > 0) + { + $new_url = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL); + + $rch = curl_copy_handle($ch); + curl_setopt($rch, CURLOPT_HEADER, true); + curl_setopt($rch, CURLOPT_NOBODY, true); + curl_setopt($rch, CURLOPT_FORBID_REUSE, false); + curl_setopt($rch, CURLOPT_RETURNTRANSFER, true); + do + { + curl_setopt($rch, CURLOPT_URL, $new_url); + $header = curl_exec($rch); + + if (curl_errno($rch)) + $code = 0; + else + { + $code = curl_getinfo($rch, CURLINFO_HTTP_CODE); + if ($code == 301 || $code == 302) + { + preg_match('/Location:(.*?)\n/', $header, $matches); + $new_url = trim(array_pop($matches)); + } + else + $code = 0; + } + } while ($code && --$maxredirections); + + curl_close($rch); + + if (!$maxredirections) + { + if ($maxredirections === null) + throw new CHttpException(301, 'Too many redirects. When following redirects, libcurl hit the maximum amount.'); + else + $maxredirections = 0; + return false; + } + curl_setopt($ch, CURLOPT_URL, $new_url); + } + } + return curl_exec($ch); + } + +}
\ No newline at end of file diff --git a/protected/extensions/egmap/EGMapControlPosition.php b/protected/extensions/egmap/EGMapControlPosition.php new file mode 100644 index 0000000..7a8b2b9 --- /dev/null +++ b/protected/extensions/egmap/EGMapControlPosition.php @@ -0,0 +1,42 @@ +<?php +/** + * + * EGMapControlPosition class + * + * @author Antonio Ramirez Cobos + * @link www.ramirezcobos.com + * + * + * @copyright + * + * Copyright (c) 2010 Antonio Ramirez Cobos + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +class EGMapControlPosition{ + + const TOP_CENTER = 'google.maps.ControlPosition.TOP_CENTER'; + const TOP_LEFT = 'google.maps.ControlPosition.TOP_LEFT'; + const TOP_RIGHT = 'google.maps.ControlPosition.TOP_RIGHT'; + const LEFT_TOP = 'google.maps.ControlPosition.LEFT_TOP'; + const RIGHT_TOP = 'google.maps.ControlPosition.RIGHT_TOP'; + const LEFT_CENTER = 'google.maps.ControlPosition.LEFT_CENTER'; + const RIGHT_CENTER = 'google.maps.ControlPosition.RIGHT_CENTER'; + const LEFT_BOTTOM = 'google.maps.ControlPosition.LEFT_BOTTOM'; + const RIGHT_BOTTOM = 'google.maps.ControlPosition.RIGHT_BOTTOM'; + const BOTTOM_LEFT = 'google.maps.ControlPosition.BOTTOM_LEFT'; + const BOTTOM_CENTER = 'google.maps.ControlPosition.BOTTOM_CENTER'; + const BOTTOM_RIGHT = 'google.maps.ControlPosition.BOTTOM_RIGHT'; +}
\ No newline at end of file diff --git a/protected/extensions/egmap/EGMapCoord.php b/protected/extensions/egmap/EGMapCoord.php new file mode 100644 index 0000000..d38476c --- /dev/null +++ b/protected/extensions/egmap/EGMapCoord.php @@ -0,0 +1,429 @@ +<?php +/** + * + * EGMapCoord Class + * Modified by Antonio Ramirez Cobos + * to be integrated to Yii as an extension + * @link http://www.ramirezcobos.com + * @since 2010-12-22 + * + * GoogleMap Coords + * @author Fabrice Bernhard + * + * @copyright + * info as this library is a modified version of Fabrice Bernhard + * + * Copyright (c) 2008 Fabrice Bernhard + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +class EGMapCoord +{ + const EARTH_RADIUS = 6380; + /** + * Latitude + * + * @var float + */ + protected $latitude; + /** + * Longitude + * + * @var float + */ + protected $longitude; + + public function __construct($latitude = null, $longitude = null) + { + $this->latitude = floatval($latitude); + $this->longitude = floatval($longitude); + } + + + /** + * @return float + * + * @author fabriceb + * @since Apr 21, 2010 + */ + public function getLatitude() + { + + return (float) $this->latitude; + } + + /** + * @return float + * + * @author fabriceb + * @since Apr 21, 2010 + */ + public function getLongitude() + { + + return (float) $this->longitude; + } + + /** + * + * @param float $latitude + * @author fabriceb + * @since Apr 21, 2010 + */ + public function setLatitude($latitude) + { + $this->latitude = floatval($latitude); + } + + /** + * + * @param float $latitude + * @author fabriceb + * @since Apr 21, 2010 + */ + public function setLongitude($longitude) + { + $this->longitude = floatval($longitude); + } + + /** + * + * @param $string + * @return EGMapCoord + * @author fabriceb + */ + public static function createFromString($string) + { + $coord_array = explode(',',$string); + if (count($coord_array)==2) + { + $latitude = floatval(trim($coord_array[0])); + $longitude = floatval(trim($coord_array[1])); + + return new EGMapCoord($latitude,$longitude); + } + + return null; + } + + /** + * + * @return string + */ + public function toJs( ) + { + return 'new google.maps.LatLng('.$this->__toString().')'; + } + + /** + * Lng to Pix + * cf. a World's map according to Google http://mt0.google.com/mt/v=ap.92&hl=en&x=0&y=0&z=0&s= + * + * @param float $lng + * @param integer $zoom + * @return integer + * @author fabriceb + * @since Feb 18, 2009 fabriceb + */ + public static function fromLngToPix($lng,$zoom) + { + $lngrad = deg2rad($lng); + $mercx = $lngrad; + $cartx = $mercx + pi(); + $pixelx = $cartx * 256/(2*pi()); + $pixelx_zoom = $pixelx * pow(2,$zoom); + + return $pixelx_zoom; + } + + /** + * Lat to Pix + * cf. a World's map according to Google http://mt0.google.com/mt/v=ap.92&hl=en&x=0&y=0&z=0&s= + * + * @param float $lat + * @param integer $zoom + * @return integer + * @author fabriceb + * @since Feb 18, 2009 fabriceb + */ + public static function fromLatToPix($lat,$zoom) + { + if ($lat == 90) + { + $pixely = 0; + } + else if ($lat == -90) + { + $pixely = 256; + } + else + { + $latrad = deg2rad($lat); + $mercy = log(tan(pi()/4+$latrad/2)); + $carty = pi() - $mercy; + $pixely = $carty * 256 / 2 / pi(); + $pixely = max(0, $pixely); // correct rounding errors near north and south poles + $pixely = min(256, $pixely); // correct rounding errors near north and south poles + } + $pixely_zoom = $pixely * pow(2,$zoom); + + return $pixely_zoom; + } + + /** + * Pix to Lng + * cf. a World's map according to Google http://mt0.google.com/mt/v=ap.92&hl=en&x=0&y=0&z=0&s= + * + * @param integer $pix + * @param integer $zoom + * @return float + * @author fabriceb + * @since Feb 18, 2009 fabriceb + */ + public static function fromPixToLng($pixelx_zoom,$zoom) + { + $pixelx = $pixelx_zoom / pow(2,$zoom); + $cartx = $pixelx / 256 * 2 * pi(); + $mercx = $cartx - pi(); + $lngrad = $mercx; + $lng = rad2deg($lngrad); + + return $lng; + } + + /** + * Pix to Lat + * cf. a World's map according to Google http://mt0.google.com/mt/v=ap.92&hl=en&x=0&y=0&z=0&s= + * + * @param integer $pix + * @param integer $zoom + * @return float + * @author fabriceb + * @since Feb 18, 2009 fabriceb + */ + public static function fromPixToLat($pixely_zoom,$zoom) + { + $pixely = $pixely_zoom / pow(2,$zoom); + if ($pixely == 0) + { + $lat = 90; + } + else if ($pixely == 256) + { + $lat = -90; + } + else + { + $carty = $pixely / 256 * 2 * pi(); + $mercy = pi() - $carty; + $latrad = 2 * atan(exp($mercy))-pi()/2; + $lat = rad2deg($latrad); + } + + return $lat; + } + + /** + * Calculates the center of an array of coordiantes + * + * @param EGMapCoord[] $coords + * @return EGMapCoord + * @author fabriceb + * @since 2009-05-02 + */ + public static function getMassCenterCoord($coords) + { + if (count($coords)==0) + { + + return null; + } + $center_lat = 0; + $center_lng = 0; + foreach($coords as $coord) + { + /* @var $coord EGMapCoord */ + $center_lat += $coord->getLatitude(); + $center_lng += $coord->getLongitude(); + } + + return new EGMapCoord($center_lat/count($coords),$center_lng/count($coords)); + } + + /** + * Calculates the center of an array of coordiantes + * + * @param EGMapCoord[] $coords + * @return EGMapCoord + * @author fabriceb + * @since 2009-05-02 + */ + public static function getCenterCoord($coords) + { + $bounds = EGMapBounds::getBoundsContainingCoords($coords); + + return $bounds->getCenterCoord(); + } + + /** + * toString method + * + * @return string + * + * @author fabriceb + * @since 2009-05-02 + * @since 2010-04-21 added (float) to force . instead of , as separator. If still not working use number_format($this->getLongitude(), 10, '.', ''); + */ + public function __toString() + { + + return ((float) $this->getLatitude()).', '.((float) $this->getLongitude()); + } + + /** + * very approximate calculation of the distance in kilometers between two coordinates + * + * @param EGMapCoord $coord2 + * @return float + * + * @author fabriceb + * @since 2009-05-03 + */ + public function distanceFrom($coord2) + { + $lat_dist = abs($this->getLatitude()-$coord2->getLatitude()); + $lng_dist = abs($this->getLongitude()-$coord2->getLongitude()); + + $rad_dist = deg2rad(sqrt(pow($lat_dist,2)+pow($lng_dist,2))); + + return $rad_dist * self::EARTH_RADIUS; + } + + /** + * exact distance with spherical law of cosines + * + * @param EGMapCoord $coord2 + * @return float + * @see http://www.zipcodeworld.com/samples/distance.php.html + * + * @author fabriceb + * @since Apr 21, 2010 + */ + public function exactDistanceSLCFrom($coord2) + { + $lat1 = $this->getLatitude(); + $lat2 = $coord2->getLatitude(); + $lon1 = $this->getLongitude(); + $lon2 = $coord2->getLongitude(); + + $theta = $lon1 - $lon2; + $dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta)); + $dist = acos($dist); + $dist = rad2deg($dist); + $miles = $dist * 60 * 1.1515; + + return $miles * 1.609344; + } + + /** + * exact distance with Haversine formula + * + * @param EGMapCoord $coord2 + * @return float + * @see http://www.movable-type.co.uk/scripts/latlong.html + * + * @author fabriceb + * @since Apr 21, 2010 + */ + public function exactDistanceFrom($coord2) + { + $lat1 = deg2rad($this->getLatitude()); + $lat2 = deg2rad($coord2->getLatitude()); + $lon1 = deg2rad($this->getLongitude()); + $lon2 = deg2rad($coord2->getLongitude()); + + $dLatHalf = ($lat2 - $lat1) / 2; + $dLonHalf = ($lon2 - $lon1) / 2; + + $a = pow(sin($dLatHalf), 2) + cos($lat1) * cos($lat2) * pow(sin($dLonHalf), 2); + $c = 2 * atan2(sqrt($a), sqrt(1 - $a)); + + return $c * self::EARTH_RADIUS; + } + + /** + * very approximate calculation of the distance in kilometers between two coordinates + * + * @param EGMapCoord $coord1 + * @param EGMapCoord $coord2 + * @return float + * + * @author fabriceb + * @since 2009-05-03 + */ + public static function distance($coord1, $coord2) + { + + return $coord1->distanceFrom($coord2); + } + + /** + * exact distance with spherical law of cosines + * + * @param EGMapCoord $coord1 + * @param EGMapCoord $coord2 + * @return float + * @see exactDistanceSLCFrom + * + * @author fabriceb + * @since Apr 21, 2010 + */ + public static function exactDistanceSLC($coord1, $coord2) + { + + return $coord1->exactDistanceSLCFrom($coord2); + } + + /** + * exact distance with Haversine formula + * + * @param EGMapCoord $coord1 + * @param EGMapCoord $coord2 + * @return float + * @see exactDistanceFrom + * + * @author fabriceb + * @since Apr 21, 2010 + */ + public static function exactDistance($coord1, $coord2) + { + + return $coord1->exactDistanceFrom($coord2); + } + + /** + * + * @param EGMapBounds $gmap_bounds + * @return boolean $is_inside + * + * @author fabriceb + * @since Jun 2, 2009 fabriceb + */ + public function isInsideBounds(EGMapBounds $gmap_bounds) + { + + return $gmap_bounds->containsGMapCoord($this); + } +}
\ No newline at end of file diff --git a/protected/extensions/egmap/EGMapDirection.php b/protected/extensions/egmap/EGMapDirection.php new file mode 100644 index 0000000..e42efeb --- /dev/null +++ b/protected/extensions/egmap/EGMapDirection.php @@ -0,0 +1,177 @@ +<?php + +/** + * EGMapDirection class + * + * @author Antonio Ramirez Cobos + * @link www.ramirezcobos.com + * + * + * @copyright + * + * Copyright (c) 2010 Antonio Ramirez Cobos + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +class EGMapDirection extends EGMapBase { + const TRAVEL_MODE_DRIVING = 'google.maps.DirectionsTravelMode.DRIVING'; + const TRAVEL_MODE_WALKING = 'google.maps.DirectionsTravelMode.WALKING'; + const TRAVEL_MODE_BICYCLING = 'google.maps.DirectionsTravelMode.BICYCLING'; + + const UNIT_SYSTEM_IMPERIAL = 'google.maps.DirectionsUnitSystem.IMPERIAL'; + const UNIT_SYSTEM_METRIC = 'google.maps.DirectionsUnitSystem.METRIC'; + + protected $renderer = null; + protected $options = array( + // Whether or not trip alternatives should be provided. + 'avoidHighways' => null, + // If true, instructs the Directions service to avoids toll roads where possible. Optional. + 'avoidTolls' => null, + // Location of destination. This can be specified as either a string to be geocoded or a LatLng. Required. + 'destination' => null, + // If set to true, the DirectionService will attempt to re-order the supplied intermediate waypoints to + // minimize overall cost of the route. If waypoints are optimized, inspect DirectionsRoute.waypoint_order + // in the response to determine the new ordering. + 'optimizeWaypoints' => null, + // Location of origin. This can be specified as either a string to be geocoded or a LatLng. Required. + 'origin' => null, + // Whether or not route alternatives should be provided. Optional. + 'provideRouteAlternatives' => null, + // Region code used as a bias for geocoding requests. + 'region' => null, + // Travel mode [DRIVING, WALKING, BICYCLING] + 'travelMode' => self::TRAVEL_MODE_WALKING, + // Preferred unit system to use when displaying distance. + // Defaults to the unit system used in the country of origin. + 'unitSystem' => null, + // Array of intermediate waypoints. Directions will be calculated from the origin to the destination by way of each waypoint in this array. + 'waypoints' => array(), + ); + + /** + * Construct GMapDirection object + * + * @param EGMapCoord $origin The coordinates of origin + * @param EGMapCoord $destination The coordinates of destination + * @param string $js_name The js var name + * @param array $options Array of option + * @author Vincent Guillon <vincentg@theodo.fr> + * @since 2009-10-30 17:20:47 + * @since 2011-01-24 by Antonio Ramirez www.ramirezcobos.com + * New algorithms + * + */ + public function __construct(EGMapCoord $origin, EGMapCoord $destination, $js_name = 'gmap_direction', $options = array()) + { + + $this->origin = $origin; + $this->destination = $destination; + $this->setOptions(array_merge($this->options, $options)); + if ($js_name !== 'gmap_direction') + $this->setJsName($js_name); + } + + public function setRenderer(EGMapDirectionRenderer $renderer) + { + $this->renderer = $renderer; + } + + public function setOrigin(EGMapCoord $origin) + { + $this->options['origin'] = $origin; + } + + public function setDestination(EGMapCoord $destination) + { + $this->options['destination'] = $destination; + } + + /** + * Options setter + * + * @param array $options + * @author Vincent Guillon <vincentg@theodo.fr> + * @since 2009-11-13 15:39:46 + * @since 2011-01-24 by Antonio Ramirez + * Modified algorithm + */ + public function setOptions($options = null) + { + if (isset($options['origin'])) + { + $this->setOrigin($options['origin']); + unset($options['origin']); + } + if (isset($options['destination'])) + { + $this->setDestination($options['destination']); + unset($options['destination']); + } + $this->options = array_merge($this->options, $options); + } + + /** + * Options getter + * + * @return array $this->options + * @author Vincent Guillon <vincentg@theodo.fr> + * @since 2009-11-13 15:38:46 + */ + public function getOptions() + { + return $this->options; + } + + /** + * Generate js code for direction + * Inspired by the work of Vincent Guillon <vincentg@theodo.fr> + * + * @param string $map_js_name The google map js var name + * @return $js_code The generated js to display direction + * @author Antonio Ramirez + * @since 2010-01-24 + * + */ + public function toJs($map_js_name = 'map') + { + if (null === $this->renderer) + throw new CException(Yii::t('EGMap', 'No Renderer Service has been provided')); + + $options = $this->getOptions(); + $js_name = $this->getJsName(); + + // set map to renderer + $this->renderer->map = $map_js_name; + + // Construct js code + $js_code = ''; + $js_code .= $this->renderer->toJs(); + $js_code .= 'var ' . $js_name . ' = new google.maps.DirectionsService();' . "\n"; + + // building Request + $js_code .= 'var ' . $js_name . 'Request = ' . EGMap::encode($this->options) . ';' . "\n"; + + $js_code .= $js_name . '.route(' . $js_name . 'Request, function(response, status)' . "\n"; + $js_code .= '{' . "\n"; + $js_code .= ' if (status == google.maps.DirectionsStatus.OK)' . "\n"; + $js_code .= ' {' . "\n"; + $js_code .= ' ' . $this->renderer->getJsName() . '.setDirections(response);' . "\n"; + $js_code .= ' }' . "\n"; + $js_code .= '});' . "\n"; + + return $js_code; + } + +}
\ No newline at end of file diff --git a/protected/extensions/egmap/EGMapDirectionRenderer.php b/protected/extensions/egmap/EGMapDirectionRenderer.php new file mode 100644 index 0000000..212bb60 --- /dev/null +++ b/protected/extensions/egmap/EGMapDirectionRenderer.php @@ -0,0 +1,123 @@ +<?php +/** + * EGMapDirectionRenderer class + * + * @author Antonio Ramirez + * @since 2010-12-24 + * @link http://www.ramirezcobos.com + * + * + * @copyright + * + * Copyright (c) 2010 Antonio Ramirez Cobos + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +class EGMapDirectionRenderer extends EGMapBase +{ + + protected $options = array( + // If true, allows the user to drag and modify the paths of + // routes rendered by this DirectionsRenderer. + 'draggable' => false, + // This property indicates whether the renderer should provide + // UI to select amongst alternative routes. By default, this flag + // is false and a user-selectable list of routes will be shown in + // the directions' associated panel. To hide that list, set + // hideRouteList to true. + 'hideRouteList' => null, + // The InfoWindow in which to render text information when a marker + // is clicked. Existing info window content will be overwritten and + // its position moved. If no info window is specified, the DirectionsRenderer + // will create and use its own info window. This property will be ignored + // if suppressInfoWindows is set to true. + 'infoWindow' => null, + // Map on which to display the directions. + // Will be overriden when enabled to a EGMapDirection + 'map' => null, + // review marker options + 'markerOptions'=>null, + // The element (node getElementById().) + 'panel' => null, + // Options for the polylines. All polylines rendered by the DirectionsRenderer + // will use these options. + // Full reference on http://code.google.com/intl/en-EN/apis/maps/documentation/javascript/reference.html#PolylineOptions + 'polylineOptions' => + array( + 'clickable'=>null, + 'strokeColor'=>null, + 'strokeOpacity'=>null, + 'strokeWeight'=>null, + 'zIndex'=>null), + // By default, the input map is centered and zoomed to the bounding box of + // this set of directions. If this option is set to true, the viewport is left + //unchanged, unless the map's center and zoom were never set. + 'preserveViewPort' => null, + // The index of the route within the DirectionsResult object. The default value is 0. + 'routeIndex'=>null, + // Suppress the rendering of the BicyclingLayer when bicycling directions are requested. + 'suppressBicyclingLayer' => null, + // Suppress the rendering of the BicyclingLayer when bicycling directions are requested. + 'suppressInfoWindows' => null, + // Suppress the rendering of markers. + 'suppressMarkers' => null, + // Suppress the rendering of polylines + 'suppressPolylines' => null + ); + + /** + * Construct GMapDirectionRenderer object + * + * @param string $js_name The js var name + * @param array $options Array of options + * @author Antonio Ramirez + * @since 2011-01-24 + */ + public function __construct( $js_name = 'gmap_direction', $options = array()) + { + $this->setOptions($options); + if( $js_name !=='gmap_direction' ) + $this->setJsName($js_name); + } + + public function setOptions( $options ){ + if(isset($options['polylineOptions'])){ + $this->setPolylineOptions($options['polylineOptions']); + unset($options['polylineOptions']); + } + $this->options = array_merge( $this->options, $options ); + } + + public function setPolylineOptions( $value ) + { + if(!is_array($value)) + { + throw new CException(Yii::t('EGMap','Property "{class}.{property}" must be of type array.', + array('{class}'=>get_class($this), '{property}'=>'polylineOptions'))); + } + $this->options['polylineOptions'] = array_merge($this->options['polylineOptions'],$value); + } + + public function toJs(){ + if( null !== $this->panel ) + $this->panel = "document.getElementById('".$this->panel."')"; + + if(count($this->options['polylineOptions'])) $this->options['polylineOptions'] = CJavaScript::encode($this->options['polylineOptions']); + + return 'var '.$this->getJsName().' = new google.maps.DirectionsRenderer('.EGMap::encode($this->options).');'."\n"; + } + + +}
\ No newline at end of file diff --git a/protected/extensions/egmap/EGMapDirectionWayPoint.php b/protected/extensions/egmap/EGMapDirectionWayPoint.php new file mode 100644 index 0000000..26e45e0 --- /dev/null +++ b/protected/extensions/egmap/EGMapDirectionWayPoint.php @@ -0,0 +1,117 @@ +<?php +/* * + * EGMapDirectionWaypoint class + * + * Modified by Antonio Ramirez www.ramirezcobos.com + * to integrate library as extension + * @since 2010-12-22 + * @link http://www.ramirezcobos.com + * + * @author Vincent Guillon <vincentg@theodo.fr> + * @since 2009-11-20 16:14:23 + * + * @copyright + * info as this library is a modified version of Fabrice Bernhard + * + * Copyright (c) 2008 Fabrice Bernhard + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +class EGMapDirectionWayPoint +{ + protected $location; + protected $stopover; + + /** + * Construct EGMapDirection object + * + * @param EGMapCoord $origin The coordinates of origin + * @param EGMapCoord $destination The coordinates of destination + * @param string $js_name The js var name + * @param array $options Array of options + * @author Vincent Guillon <vincentg@theodo.fr> + * @since 2009-10-30 17:20:47 + */ + public function __construct($location = null, $stopover = true) + { + $this->setLocation($location); + $this->setStopOver($stopover); + } + + /** + * $location getter + * + * @return EGMapCoord $this->location + * @author Vincent Guillon <vincentg@theodo.fr> + * @since 2009-11-20 16:16:55 + */ + public function getLocation() + { + + return $this->location; + } + + /** + * $stopover getter + * + * @return boolen $this->stopover + * @author Vincent Guillon <vincentg@theodo.fr> + * @since 2009-11-20 16:17:14 + */ + public function getStopOver() + { + + return $this->stopover; + } + + /** + * $location setter + * + * @param EGMapCoord $location + * @author Vincent Guillon <vincentg@theodo.fr> + * @since 2009-11-20 16:17:42 + * @since 2010-12-22 Modified for Yii Antonio Ramirez + */ + public function setLocation(EGMapCoord $location = null) + { + $this->location = $location; + } + + /** + * $stopover setter + * + * @param boolean $stopover + * @author Vincent Guillon <vincentg@theodo.fr> + * @since 2009-11-20 16:19:37 + */ + public function setStopOver($stopover = true) + { + $this->stopover = $stopover; + } + + /** + * Generate javascript code fo GMapDirection waypoints option + * + * @return string + * @author Vincent Guillon <vincentg@theodo.fr> + * @since 2009-11-20 16:31:42 + */ + public function toJs() + { + $stopover = $this->getStopOver() ? 'true' : 'false'; + + return '{location : '.$this->getLocation()->toJs().', stopover: '.$stopover.'}'; + } +}
\ No newline at end of file diff --git a/protected/extensions/egmap/EGMapElevationInfo.php b/protected/extensions/egmap/EGMapElevationInfo.php new file mode 100644 index 0000000..78c7b56 --- /dev/null +++ b/protected/extensions/egmap/EGMapElevationInfo.php @@ -0,0 +1,226 @@ +<?php + +/** + * + * EGMapElevationInfo + * + * + * A class to elevation info service + * @author Antonio Ramirez + * + * @copyright + * + * Copyright (c) 2011 Antonio Ramirez + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +class EGMapElevationInfo +{ + /** + * + * @var type + */ + protected $coords = array(); + + protected $locations = array(); + + /** + * Constructs a EGMapElevationInfo object from a given coords String|EGMapCoord|Array + * + * @param mixed $coords the coordinates to get elevation info + * @author Antonio Ramirez + */ + public function __construct($coords = null) + { + $this->setCoords($coords); + } + + /** + * Returns the coordinate array + * @return array + */ + public function getCoords() + { + + return $this->coords; + } + /** + * Sets the coordinates array + * @param array $coords + * @author Antonio Ramirez + */ + public function setCoords($coords) + { + if(!is_array($coords)) + $coords = array($coords); + + foreach($coords as $coord) + $this->addCoord($coord); + } + /** + * Adds a coordinate to the array, can be a string or a EGMapCoord object + * @param mixed $coord + * @author Antonio Ramirez + */ + public function addCoord($coord) + { + if($coord instanceof EGMapCoord) + $coord = $coord->__toString (); + + $this->coords[] = str_replace(' ','',$coord); + + } + /** + * + * @return array of EGMapElevationInfoResult objects if api call was + * successfull + */ + public function getLocations() + { + return $this->locations; + } + /** + * Request the elevation info using Google Maps' API JSON + * + * @param EGMapClient $gmap_client + * @param $forceEncode whether to encode the lat/lng points + * @return array of EGMapElevationInfoResult if successful + * @author Antonio Ramirez + */ + public function elevationRequestJson($gmap_client, $forceEncode = true) + { + if(empty($this->coords)) return false; + + $this->locations = array(); + + $coords = array(); + + /* At least 3 coords otherwise is not point */ + if($forceEncode && count($this->coords)>2) + $coords = $this->prepareEncodedCoords($this->coords); + else + $coords = implode('|', $this->coords); + + $raw_data = $gmap_client->getElevationInfo($coords); + + $data = CJSON::decode($raw_data); + + if ('OK' != $data['status']) + { + return false; + } + + foreach($data['results'] as $result) + { + $info = new EGMapElevationInfoResult(); + $info->lat = $result['location']['lat']; + $info->lng = $result['location']['lng']; + $info->elevation = $result['elevation']; + $info->resolution = $result['resolution']; + $this->locations[] = $info; + } + return $this->locations; + } + /** + * Request the elevation info using Google Maps' API XML + * + * @param EGMapClient $gmap_client + * @param $forceEncode whether to encode the lat/lng points + * @return array of EGMapElevationInfoResult if successful + * @author Antonio Ramirez + */ + public function elevationRequestXml($gmap_client, $forceEncode = true) + { + if(empty($this->coords)) return false; + + $this->locations = array(); + + $coords = array(); + + /* At least 3 coords otherwise is not point */ + if($forceEncode && count($this->coords)>2) + $coords = $this->prepareEncodedCoords($this->coords); + else + $coords = implode('|', $this->coords); + + $raw_data = $gmap_client->getElevationInfo($coords, 'xml'); + + $xml = simplexml_load_string($raw_data); + + if ('OK' != $xml->status) + { + return false; + } + + foreach ($xml->result as $component) + { + $info = new EGMapElevationInfoResult(); + $info->lat = $component->location->lat; + $info->lng = $component->location->lng; + $info->elevation = $component->elevation; + $info->resolution = $component->resolution; + $this->locations[] = $info; + } + return $this->locations; + } + /** + * Encodes coordinates based on Google polyline algorithm + * @see http://code.google.com/intl/es/apis/maps/documentation/utilities/polylinealgorithm.html + * @param array $coords + * @return string coordinates + */ + protected function prepareEncodedCoords($coords) + { + $enc = new EGMapPolylineEncoder(); + $ecoords = array(); + foreach($coords as $coord) + { + $ecoords[] = explode(',', $coord); + } + return 'enc:' . $enc->encode($ecoords); + } +} + +/** + * EGMapElevationInfoResult class + * + * General object to fill with results of different adapters + */ +class EGMapElevationInfoResult { + /** + * + * @var array $props that hold attributes + */ + protected $props; + /** + * Magic method __set + * @param string $name + * @param string $value + */ + public function __set($name, $value) + { + $this->props[$name] = $value; + } + /** + * Magic method __get + * @param string $name the attribute name + * @return attribute value | null if not exists + */ + public function __get($name) + { + return isset($this->props[$name])?$this->props[$name]:null; + } + +} diff --git a/protected/extensions/egmap/EGMapEvent.php b/protected/extensions/egmap/EGMapEvent.php new file mode 100644 index 0000000..f050724 --- /dev/null +++ b/protected/extensions/egmap/EGMapEvent.php @@ -0,0 +1,154 @@ +<?php +/** + * + * EGMapEvent + * + * Modified by Antonio Ramirez + * @since 2011-01-22 + * @link http://www.ramirezcobos.com + * + * changeLog: + * + * 2011-07-02 Included support for addDOMEventListenerOnce and addEventListenerOnce + * modified by: Johnatan -http://www.yiiframework.com/forum/index.php?/user/7513-johnatan/) + * 2011-01-22 Included toJs for custom event type selection (DOM or DEFAULT) + * + * A googleMap Event + * @author Fabrice Bernhard + * + * + * @copyright + * info as this library is a modified version of Fabrice Bernhard + * + * Copyright (c) 2008 Fabrice Bernhard + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +class EGMapEvent +{ + const TYPE_EVENT_DEFAULT = 'DEFAULT'; + const TYPE_EVENT_DEFAULT_ONCE = 'DEFAULT_ONCE'; + const TYPE_EVENT_DOM = 'DOM'; + const TYPE_EVENT_DOM_ONCE = 'DOM_ONCE'; + + protected $trigger; + protected $function; + protected $encapsulate_function; + protected $type = self::TYPE_EVENT_DEFAULT; + + + /** + * @param string $trigger action that will trigger the event + * @param string $function the javascript function to be executed + * @param string $encapsulate_function + * @author Fabrice Bernhard + */ + public function __construct($trigger,$function,$encapsulate_function=true, $type=self::TYPE_EVENT_DEFAULT) + { + $this->trigger = $trigger; + $this->function = $function; + $this->encapsulate_function = $encapsulate_function; + $this->setType($type); + } + /** + * + * Sets the type of event, by default Google Event + * @param string $type + * @throws CException + */ + public function setType( $type ){ + if( $type !== self::TYPE_EVENT_DEFAULT && $type !== self::TYPE_EVENT_DEFAULT_ONCE && + $type !== self::TYPE_EVENT_DOM && $type !== self::TYPE_EVENT_DOM_ONCE ) + throw new CException( Yii::t('EGMap', 'Unrecognized Event type') ); + $this->type = $type; + } + /** + * + * Returns type of event + * @return string + */ + public function getType( ){ + return $this->type; + } + + /** + * @return string $trigger action that will trigger the event + */ + public function getTrigger() + { + + return $this->trigger; + } + /** + * @return string $function the javascript function to be executed + */ + public function getFunction() + { + if (!$this->encapsulate_function) + return $this->function; + else + return 'function() {'.$this->function.'}'; + } + + /** + * returns the javascript code for attaching a Google event to a javascript_object + * + * @param string $js_object_name + * @return string + * @author Fabrice Bernhard + * @since 2011-07-02 Johnatan added Once support + */ + public function getEventJs($js_object_name, $once=false) + { + $once = ($once)?'Once':''; + return 'google.maps.event.addListener'.$once.'('.$js_object_name.', "'.$this->getTrigger().'", '.$this->getFunction().');'.PHP_EOL; + } + + /** + * returns the javascript code for attaching a dom event to a javascript_object + * + * @param string $js_object_name + * @return string + * @author Fabrice Bernhard + * @since 2011-07-02 Johnatan + */ + public function getDomEventJs($js_object_name, $once=false) + { + $once = ($once)?'Once':''; + return 'google.maps.event.addDomListener'.$once.'('.$js_object_name.', "'.$this->getTrigger().'", '.$this->getFunction().');'.PHP_EOL; + } + /** + * returns the javascript code for attaching a Google event or a dom event to a javascript_object + * + * @param string $js_object_name + * @return string of event type + * @author Antonio Ramirez + * @since 2011-07-02 Johnatan added Once Support + */ + public function toJs( $js_object_name ){ + switch ($this->type) { + case self::TYPE_EVENT_DEFAULT_ONCE: + return $this->getEventJs($js_object_name, true); + case self::TYPE_EVENT_DOM: + return $this->getDomEventJs($js_object_name); + case self::TYPE_EVENT_DOM_ONCE: + return $this->getDomEventJs($js_object_name, true); + case self::TYPE_EVENT_DEFAULT: + default: + return $this->getEventJs($js_object_name); + } + } + +}
\ No newline at end of file diff --git a/protected/extensions/egmap/EGMapGeocodeTool.php b/protected/extensions/egmap/EGMapGeocodeTool.php new file mode 100644 index 0000000..a4e9a0d --- /dev/null +++ b/protected/extensions/egmap/EGMapGeocodeTool.php @@ -0,0 +1,303 @@ +<?php +/** + * EGMapGeocodeTool class + * + * Renders a tool for geocoding and reverse geocoding, that also can work + * in synchronization with different form fields. + * + * @author antonio + */ +class EGMapGeocodeTool +{ + public $latitude = 39.737827146489174; + public $longitude = 3.2830574338912477; + public $zoom = 4; + public $popupOptions; + public $searchBox=false; + public $width = '100%'; + public $height = '100px'; + public $geocodeOnShow = false; + public $afterInitEvents = array(); + /** + * ID's of fields for input that can be filled automatically by the reverse geocoding + */ + public $formId = null; + public $latId = null; + public $lngId = null; + public $addressId = null; + public $zipId = null; + public $cityId = null; + public $regionId = null; + public $countryId = null; + + /** + * @param array $config the configuration for initializing the GeocodeTool... + * any attribute from this class can be set by giving it a value in this array + */ + public function __construct($config) + { + if(is_array($config)) + foreach($config as $name=>$value) + $this->{$name} = $value; + } + + public function render() + { + $this->registerScripts(); + $this->renderMap(); + + if ($this->popupOptions !== null) + { + $this->renderPopupMap(); + } + } + + protected function renderMap() + { + $gMap = new EGMap(); + $gMap->setJsName('geomap'); + $gMap->width = $this->width; + $gMap->height = $this->height; + $gMap->zoom = $this->zoom; + $gMap->setCenter($this->latitude, $this->longitude); + $gMap->addGlobalVariable('geocoder'); + $gMap->addGlobalVariable('geomap', 'null'); + if ($this->popupOptions === null) + { + $gMap->addGlobalVariable('hgeomap', 'null'); + $gMap->addGlobalVariable('hgmarker', 'null'); + } + $gMap->addEvent(new EGMapEvent('click', 'function(e){panToMap(geomap,e.latLng,hgeomap);}', false)); + $gMap->appendMapTo('#geomap'); + + $afterInit = array( + 'geocoder = new google.maps.Geocoder();', + 'gmarker = new google.maps.Marker({ + position: geomap.getCenter(), + map: geomap, + draggable: true + });', + 'google.maps.event.addListener(gmarker, "dragend", function(e) { + panToMap(geomap,e.latLng,hgeomap); + });' + ); + + echo CHtml::openTag('div', array( 'style' => 'width:' . $this->width)); + + if($this->searchBox) + { + $this->renderAddressSearchBox ('geoaddress'); + $afterInit[] = 'qDefaultText.init({"geoaddress": "Enter address here"});'; + } + if($this->geocodeOnShow) + $afterInit[] = 'panToMap(geomap,geomap.getCenter(),hgeomap)'; + + $gMap->renderMap($afterInit); + + echo '<div style="clear:both;height:1px"></div>'; + echo CHtml::openTag('ul', array('class' => 'message', 'style' => 'margin-bottom:-2px;margin-right:-2px')); + echo '<li>Drag the marker or click the map to specify new address.</li>'; + echo CHtml::closeTag('ul'); + echo '<div id="geomap" style="width:' . $this->width . ';height:' . $this->height . 'px"></div>'; + if ($this->popupOptions !== null) + echo '<a href="#" id="open-big-map" class="btn-big" style="margin-top:3px;margin-right:30px">Open Big Map</a>'; + + echo CHtml::closeTag('div'); + } + + protected function renderPopupMap() + { + $gMap = new EGMap(); + $gMap->setJsName('hgeomap'); + $gMap->addGlobalVariable('hgmarker'); + $gMap->width = isset($this->popupOptions['mapWidth']) ? $this->popupOptions['mapWidth'] : '100%'; + $gMap->height = isset($this->popupOptions['mapHeight']) ? $this->popupOptions['mapHeight'] : '600px'; + $gMap->zoom = 6; + $gMap->setCenter($this->latitude, $this->longitude); + $gMap->addEvent(new EGMapEvent('click', 'function(e){panToMap(geomap,e.latLng,hgeomap);}', false)); + $gMap->appendMapTo('#popup-map'); + $this->popupOptions['width'] = isset($this->popupOptions['width']) ? $this->popupOptions['width'] : '800px'; + + $afterInit = array( + 'hgmarker = new google.maps.Marker({ + position: hgeomap.getCenter(), + map: hgeomap, + draggable: true + });', + 'google.maps.event.addListener(hgmarker, "dragend", function(e) { + panToMap(geomap,e.latLng,hgeomap); + });', + '$("#open-big-map").click(function(e){ + e.preventDefault(); + $("#hgeomap").dialog({resizable:false,title:"Location",width:"'.$this->popupOptions['width'].'"}); + google.maps.event.trigger(hgeomap, "resize"); + hgeomap.setCenter(geomap.getCenter()); + return false; + });' + ); + + echo CHtml::openTag('div', array('id'=>'hgeomap','style' => 'display:none')); + + if(isset($this->popupOptions['searchBox']) && $this->popupOptions['searchBox']) + $this->renderAddressSearchBox ('hgeoaddress'); + if(!is_array($this->afterInitEvents)) + $this->afterInitEvents = array($this->afterInitEvents); + + $gMap->renderMap(array_merge($this->afterInitEvents,$afterInit)); + + echo '<div id="popup-map" ></div>'; + echo CHtml::closeTag('div'); + } + + protected function renderAddressSearchBox($id) + { + echo '<div class="set-row-2">'; + echo CHtml::textField($id, '', array('class'=>'input-2','id'=>$id)); + echo CHtml::link('Go to','#', array('class'=>'btn-medium', 'onclick'=>'return geocode("'.$id.'");')); + echo '</div>'; + echo '<div style="clear:both;height:1px"></div>'; + } + + protected function registerScripts() + { + $updateFieldsJS=''; + $fields=array(); + if($this->latId !== null ) + $updateFieldsJS.="$('#{$this->latId}').val(ll.lat());"; + if($this->lngId !== null) + $updateFieldsJS.="$('#{$this->lngId}').val(ll.lng());"; + $updateFieldsJS.="reverseGeocode();"; + + $reverseJS=''; + if($this->addressId !== null){ + $reverseJS.="$('#{$this->addressId}').val(geoValue('route'));"; + $fields[] = '#'.$this->addressId; + } + if($this->zipId !== null){ + $reverseJS.="$('#{$this->zipId}').val(geoValue('postal_code'));"; + $fields[] = '#'.$this->zipId; + } + if($this->cityId !== null) + { + $reverseJS.="var city = geoValue('locality');"; + $reverseJS.="if(city=='') city = geoValue('sublocality');"; + $reverseJS.="$('#{$this->cityId}').val(city);"; + $fields[] = '#'.$this->cityId; + } + if($this->regionId !== null) + { + $reverseJS.="$('#{$this->regionId}').val(geoValue('administrative_area_level_1'));"; + $fields[] = '#'.$this->regionId; + } + if($this->countryId !== null) + { + $reverseJS.="var country = geoValue('country');"; + $reverseJS.="$('#{$this->countryId}').val(country);"; + $fields[] = '#'.$this->countryId; + } + if($this->formId !== null) + { + $reverseJS.=<<<EOJS +var form=$('#{$this->formId}'); +if(form.length && $.fn.yiiactiveform){ + var settings = form.data('settings'); + $.each(settings.attributes, function(){this.status = 3;}); + $.fn.yiiactiveform.validate(form,function(data){ + $.each(settings.attributes, function(i, attribute){ + $.fn.yiiactiveform.updateInput(attribute, data, form); + }); + }); +} +EOJS; + } + $fieldsStr = implode(',', $fields); + $fieldsJS = + "$('#{$this->latId}, #{$this->lngId}').change(function(){ + var latLng = new google.maps.LatLng($('#{$this->latId}').val(), $('#{$this->lngId}').val()); + panToMap(geomap,latLng,hgeomap); + }); + //var fields = ['".implode("','", $fields)."']; + //$('{$fieldsStr}').change(function(){ + // $('#{$this->latId}, #{$this->lngId}').val(''); + //}); + "; + + $js = <<<EOD + function panToMap(m,latLng,m2){ + m.panTo(latLng); + if(m2!=null) m2.panTo(latLng); + if(gmarker.getPosition().lat()!=latLng.lat()) + gmarker.setPosition(latLng); + if(hgmarker!=null && hgmarker.getPosition().lat()!=latLng.lat()) + hgmarker.setPosition(latLng); + updateFields(latLng); + } + function dragEnd(e){ + panToMap(geomap,e.latLng,hgeomap); + } + function updateFields(ll){ + $updateFieldsJS + } + function reverseGeocode() { + lastReverseGeocode = new Date(); + geocoder.geocode({latLng:geomap.getCenter()},reverseGeocodeResult); + } + function reverseGeocodeResult(results, status) { + currentReverseGeocodeResponse = results; + if(status == 'OK') { + if(results.length == 0) + return; + else{ + var str = results[0].formatted_address; + if($('#geoaddress').length) $('#geoaddress').val(str); + if($('#hgeoaddress').length) $('#hgeoaddress').val(str); + $reverseJS + } + } else + return; + } + function geocode(id) { + var address = $("#"+id).val(); + if ($.trim(address)=='Enter address here') return false; + geocoder.geocode({'address': address, 'partialmatch': true}, geocodeResult); + return false; + } + function geocodeResult(results, status) { + if (status == 'OK' && results.length > 0){ + if(geomap){ + geomap.fitBounds(results[0].geometry.viewport); + gmarker.setPosition(geomap.getCenter()); + updateFields(geomap.getCenter()); + } + if(hgeomap){ + hgeomap.fitBounds(results[0].geometry.viewport); + hgmarker.setPosition(geomap.getCenter()); + } + reverseGeocodeResult(results, status); + }else + qAlert("Geocode was not successful for the following reason: " + status); + } + function geoValue(type){ + var i, j, result, types, results; + results = currentReverseGeocodeResponse[0].address_components; + // Loop through the Geocoder result set. Note that the results + // array will change as this loop can self iterate. + for (i = 0; i < results.length; i++) { + result = results[i]; + types = result.types; + for (j = 0; j < types.length; j++) { + if (types[j] === type) + return result.long_name || ''; + } + } + return ''; + } +EOD; + $cs = Yii::app()->clientScript; + $cs->registerScript('EGMapGeocodeToolJS', $js, CClientScript::POS_END); + if($this->latId && $this->lngId) + $cs->registerScript('EGeocodeToolJSor',$fieldsJS, CClientScript::POS_READY); + } +} + +?>
\ No newline at end of file diff --git a/protected/extensions/egmap/EGMapGeocodedAddress.php b/protected/extensions/egmap/EGMapGeocodedAddress.php new file mode 100644 index 0000000..2836f4e --- /dev/null +++ b/protected/extensions/egmap/EGMapGeocodedAddress.php @@ -0,0 +1,391 @@ +<?php + +/** + * + * EGMapGeocodedAddress + * + * Modified by Antonio Ramirez Cobos + * @link http://www.ramirezcobos.com + * + * A class to geocode addresses + * @author Fabrice Bernhard + * + * @copyright + * info as this library is a modified version of Fabrice Bernhard + * + * Copyright (c) 2008 Fabrice Bernhard + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +class EGMapGeocodedAddress +{ + + protected $raw_address = null; + protected $lat = null; + protected $lng = null; + protected $accuracy = null; + protected $geocoded_city = null; + protected $geocoded_country_code = null; + protected $geocoded_country = null; + protected $geocoded_address = null; + protected $geocoded_street = null; + protected $geocoded_postal_code = null; + + /** + * Constructs a gMapGeocodedAddress object from a given $raw_address String + * + * @param string $raw_address + * @author Fabrice Bernhard + */ + public function __construct($raw_address) + { + $this->raw_address = $raw_address; + } + + /** + * + * @return string $raw_address + * @author fabriceb + * @since 2009-06-17 + */ + public function getRawAddress() + { + + return $this->raw_address; + } + + /** + * Geocodes the address using the Google Maps CSV webservice + * + * @param EGMapClient $gmap_client + * @return integer $accuracy + * @author Fabrice Bernhard + * @since 2011-04-21 Matt Cheale Updated to parse API V3 JSON response. + */ + public function geocode($gmap_client) + { + $raw_data = $gmap_client->getGeocodingInfo($this->getRawAddress()); + $data = CJSON::decode($raw_data); + + if ('OK' != $data['status']) + { + return false; + } + + $location = $data['results'][0]['geometry']; + + $this->lat = $location['location']['lat']; + $this->lng = $location['location']['lng']; + $this->accuracy = $location['location_type']; + + return $this->accuracy; + } + + /** + * Reverse geocoding + * + * @return integer + * @author Vincent Guillon <vincentg@theodo.fr> + * @since 2010-03-04 + * @since 2011-03-23 Matt Cheale Updated mapping from v2 to v3 of the API result format. + */ + public function reverseGeocode($gmap_client) + { + $raw_data = $gmap_client->getReverseGeocodingInfo($this->getLat(), $this->getLng()); + $geocoded_array = CJSON::decode($raw_data, true); + + if ($geocoded_array['status'] != 'OK') + { + return false; + } + + $result = $geocoded_array['results'][0]; + $address_components = $result['address_components']; + $this->raw_address = $result['formatted_address']; + $this->geocoded_address = $result['formatted_address']; + $this->accuracy = $result['types'][0]; + + $map = array( + 'street_address' => 'geocoded_street', + 'route' => 'geocoded_street', + 'country' => 'geocoded_country', + 'locality' => 'geocoded_city', + 'postal_code' => 'geocoded_postal_code', + ); + + foreach ($address_components as $component) + { + foreach ($component['types'] as $type) + { + switch ($type) + { + case 'street_address': + case 'route': + $this->geocoded_street = $component['long_name']; + break; + + case 'country': + $this->geocoded_country = $component['long_name']; + $this->geocoded_country_code = $component['short_name']; + break; + + case 'locality': + $this->geocoded_city = $component['long_name']; + break; + + case 'postal_code': + $this->geocoded_postal_code = $component['long_name']; + break; + + default: + // Do nothing + } + } + } + + return $this->accuracy; + } + + /** + * Geocodes the address using the Google Maps XML webservice, which has more information. + * Unknown values will be set to NULL. + * @todo Change to SimpleXML + * @param EGMapClient $gmap_client + * @return integer $accuracy + * @author Fabrice Bernhard + * @since 2010-12-22 modified by utf8_encode removed Antonio Ramirez + * @since 2011-04-21 Matt Cheale Updated to parse API V3 JSON response. + */ + public function geocodeXml($gmap_client) + { + $raw_data = $gmap_client->getGeocodingInfo($this->getRawAddress(), 'xml'); + $xml = simplexml_load_string($raw_data); + + if ('OK' != $xml->status) + { + return false; + } + + foreach ($xml->result->address_component as $component) + { + $longName = (string) $component->long_name; + $shortName = (string) $component->short_name; + foreach ($component->type as $type) + { + switch ($type) + { + case 'street_address': + case 'route': + $this->geocoded_street = $longName; + break; + + case 'country': + $this->geocoded_country = $longName; + $this->geocoded_country_code = $shortName; + break; + + case 'locality': + $this->geocoded_city = $shortName; + break; + + case 'postal_code': + $this->geocoded_postal_code = $longName; + break; + + default: + // Do nothing + } + } + } + + $this->lat = (double) $xml->result->geometry->location->lat; + $this->lng = (double) $xml->result->geometry->location->lng; + + $this->accuracy = (string) $xml->result->geometry->location_type; + + return $this->accuracy; + } + + /** + * Returns the latitude + * @return float $latitude + */ + public function getLat() + { + + return $this->lat; + } + + /** + * Returns the longitude + * @return float $longitude + */ + public function getLng() + { + + return $this->lng; + } + + /** + * Returns the Geocoding accuracy + * @return integer $accuracy + */ + public function getAccuracy() + { + + return $this->accuracy; + } + + /** + * Returns the address normalized by the Google Maps web service + * @return string $geocoded_address + */ + public function getGeocodedAddress() + { + + return $this->geocoded_address; + } + + /** + * Returns the city normalized by the Google Maps web service + * @return string $geocoded_city + */ + public function getGeocodedCity() + { + + return $this->geocoded_city; + } + + /** + * Returns the country code normalized by the Google Maps web service + * @return string $geocoded_country_code + */ + public function getGeocodedCountryCode() + { + + return $this->geocoded_country_code; + } + + /** + * Returns the country normalized by the Google Maps web service + * @return string $geocoded_country + */ + public function getGeocodedCountry() + { + + return $this->geocoded_country; + } + + /** + * Returns the postal code normalized by the Google Maps web service + * @return string $geocoded_postal_code + */ + public function getGeocodedPostalCode() + { + + return $this->geocoded_postal_code; + } + + /** + * Returns the street name normalized by the Google Maps web service + * @return string $geocoded_country_code + */ + public function getGeocodedStreet() + { + + return $this->geocoded_street; + } + + /** + * @param string $raw raw address to set + */ + public function setRawAddress($raw) + { + $this->raw_address = $raw; + } + + /** + * @param float $lat latitude to set + */ + public function setLat($lat) + { + $this->lat = $lat; + } + + /** + * @param float $lat longitude to set + */ + public function setLng($lng) + { + $this->lng = $lng; + } + + /** + * @param float $lat accuracy to set + */ + public function setAccuracy($accuracy) + { + $this->accuracy = $accuracy; + } + + /** + * @param string $val geocoded city + */ + public function setGeocodedCity($val) + { + $this->geocoded_city = $val; + } + + /** + * @param string $val geocoded country code + */ + public function setGeocodedCountryCode($val) + { + $this->geocoded_country_code = $val; + } + + /** + * @param string $val geocoded country code + */ + public function setGeocodedCountry($val) + { + $this->geocoded_country = $val; + } + + /** + * @param string $val geocoded address + */ + public function setGeocodedAddress($val) + { + $this->geocoded_address = $val; + } + + /** + * @param string $val geocoded street + */ + public function setGeocodedStreet($val) + { + $this->geocoded_street = $val; + } + + /** + * @param string $val geocoded postal_code + */ + public function setGeocodedPostalCode($val) + { + $this->geocoded_postal_code = $val; + } + +} diff --git a/protected/extensions/egmap/EGMapInfoBox.php b/protected/extensions/egmap/EGMapInfoBox.php new file mode 100644 index 0000000..2cbf257 --- /dev/null +++ b/protected/extensions/egmap/EGMapInfoBox.php @@ -0,0 +1,144 @@ +<?php + +/** + * TODO: add load content via ajax functionality + * function load_content(marker, id){ + * $.ajax({ + * url: 'aulas/show/' + id, + * success: function(data){ + * infowindow.setContent(data); + * infowindow.open(map, marker); + * } + * }); + * } + * Then change the listener: + * + * google.maps.event.addListener(marker, 'click', function() { + * infobox.close(); + * load_content(marker, a.aula.id); + * }); + * markers.push(marker); + * }); + * + * EGMapInfoBox class + * A GoogleMap InfoBox + * + * @since 2011-10-12 + * @link http://www.ramirezcobos.com + * + * @author Antonio Ramirez Cobos + * + * + * Copyright (c) 2010 Antonio Ramirez Cobos + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +class EGMapInfoBox extends EGMapInfoWindow { + + /** + * + * Config options + * @link http://code.google.com/intl/en-EN/apis/maps/documentation/javascript/reference.html#InfoWindow + * @var array + */ + protected $box_options = array( + // Align the bottom left corner of the InfoBox to the position + // location (default is false which means that the top left corner + // of the InfoBox is aligned). + 'alignBottom' => null, + // The name of the CSS class defining the styles for the InfoBox container. + // The default name is infoBox. + 'boxClass' => null, + // An object literal whose properties define specific CSS style + // values to be applied to the InfoBox. Style values defined + // here override those that may be defined in the boxClass style + // sheet. If this property is changed after the InfoBox has been + // created, all previously set styles (except those defined in + // the style sheet) are removed from the InfoBox before the new + // style values are applied. + 'boxStyle' => null, + // The CSS margin style value for the close box. The default is + // "2px" (a 2-pixel margin on all sides). + 'closeBoxMargin' => '"2px"', + // The URL of the image representing the close box. Note: The + // default is the URL for Google's standard close box. Set this + // property to "" if no close box is required. + 'closeBoxUrl'=>null, + // Propagate mousedown, click, dblclick, and contextmenu events + // in the InfoBox (default is false to mimic the behavior of a + // google.maps.InfoWindow). Set this property to true if the InfoBox + // is being used as a map label. iPhone note: This property setting + // has no effect; events are always propagated. + 'enableEventPropagation'=>null, + // Minimum offset (in pixels) from the InfoBox to the map edge + // after an auto-pan. + 'infoBoxClearance'=>null, + // Hide the InfoBox on open (default is false). + 'isHidden'=>null, + // The pane where the InfoBox is to appear (default is "floatPane"). + // Set the pane to "mapPane" if the InfoBox is being used as a map + // label. Valid pane names are the property names for the google.maps.MapPanes object. + 'pane'=>null, + ); + + /** + * @param string content + * @param array $options + * @param string $js_name + * @param array $events + * @author Maxime Picaud + * @since 7 sept. 2009 + */ + public function __construct($content, $js_name='info_box', $options = array(), $events=array()) + { + $this->options = CMap::mergeArray($this->options, $this->box_options); + + if ($js_name !== 'info_box') + $this->setJsName($js_name); + + $this->setContent($content); + + $this->setOptions($options); + $this->events = $events; + } + + /** + * @param string $map_js_name + * @return string Javascript code to create the infoBox + * @author Fabrice Bernhard + * @since 2011-10-12 by Antonio Ramirez + */ + public function toJs($map_js_name = 'map') + { + + $return = ''; + $return .= $this->getJsName() . ' = new InfoBox(' . EGMap::encode($this->options) . ');' . PHP_EOL; + + foreach ($this->custom_properties as $attribute => $value) + { + $return .= 'var ' . $this->getJsName() . "." . $attribute . " = '" . $value . "';" . PHP_EOL; + } + foreach ($this->events as $event) + { + $return .= $event->getEventJs($this->getJsName()); + } + return $return; + } + + public function getEncodedOptions() + { + return EGMap::encode(parent::getOptions()); + } +} diff --git a/protected/extensions/egmap/EGMapInfoWindow.php b/protected/extensions/egmap/EGMapInfoWindow.php new file mode 100644 index 0000000..ac705f3 --- /dev/null +++ b/protected/extensions/egmap/EGMapInfoWindow.php @@ -0,0 +1,257 @@ +<?php +/** + * TODO: add load content via ajax functionality + * function load_content(marker, id){ + * $.ajax({ + * url: 'aulas/show/' + id, + * success: function(data){ + * infowindow.setContent(data); + * infowindow.open(map, marker); + * } + * }); + *} + *Then change the listener: + * + * google.maps.event.addListener(marker, 'click', function() { + * infowindow.close(); + * load_content(marker, a.aula.id); + * }); + * markers.push(marker); + * }); + * + * EGMapInfoWindow class + * A GoogleMap InfoWindow + * + * @since 2011-01-22 Modified by Antonio Ramirez + * @link http://www.ramirezcobos.com + * + * @TODO: change $events to CTypeMap('EGMapEvent') type + * + * @author Maxime Picaud + * + * + * @copyright + * info as this library is a modified version of Fabrice Bernhard + * + * Copyright (c) 2008 Fabrice Bernhard + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +class EGMapInfoWindow extends EGMapBase +{ + /** + * + * Config options + * @link http://code.google.com/intl/en-EN/apis/maps/documentation/javascript/reference.html#InfoWindow + * @var array + */ + protected $options = array( + // String Content to display in the InfoWindow. This can be an HTML element, + // a plain-text string, or a string containing HTML. The InfoWindow will be + // sized according to the content. To set an explicit size for the content, + // set content to be a HTML element with that size. + 'content' => null, + + // boolean Disable auto-pan on open. By default, the info window will pan + // the map so that it is fully visible when it opens. + 'disableAutoPan' => null, + + // number Maximum width of the infowindow, regardless of content's width. + // This value is only considered if it is set before a call to open. To change + // the maximum width when changing content, call close, setOptions, and then open. + 'maxWidth' => null, + + // Size The offset, in pixels, of the tip of the info window from the point on + // the map at whose geographical coordinates the info window is anchored. If an + // InfoWindow is opened with an anchor, the pixelOffset will be calculated from + // the top-center of the anchor's bounds. + 'pixelOffset' => null, + + // LatLng The LatLng at which to display this InfoWindow. If the InfoWindow is + // opened with an anchor, the anchor's position will be used instead. + 'position' => null, + + //number All InfoWindows are displayed on the map in order of their zIndex, with + // higher values displaying in front of InfoWindows with lower values. By default, + // InfoWinodws are displayed according to their latitude, with InfoWindows of lower + // latitudes appearing in front of InfoWindows at higher latitudes. InfoWindows are + // always displayed in front of markers. + 'zIndex' => null, + ); + + protected $events = array(); + protected $custom_properties = array(); + + /** + * @param string content + * @param array $options + * @param string $js_name + * @param array $events + * @author Maxime Picaud + * @since 7 sept. 2009 + */ + public function __construct( $content, $js_name='info_window', $options = array(), $events=array() ) + { + if( $js_name !== 'info_window' ) + $this->setJsName($js_name); + + $this->setContent($content); + + $this->setOptions($options); + $this->events = $events; + } + + /** + * + * @param string $content + * @author Maxime Picaud + * @since 7 sept. 2009 + * @since 2011-01-25 by Antonio Ramirez + * Included support to have content + * from a DOM node + */ + public function setContent( $content ) + { + if(strpos( strtolower($content), 'getelementbyid')>0) + { + $this->options['content'] = $content; + } + else + { + $content = preg_replace('/\r\n|\n|\r/', "\\n", $content); + $content = preg_replace('/(["\'])/', '\\\\\1', $content); + + $this->options['content'] = '"'.$content.'"'; + } + } + + public function getContent( ) + { + return $this->options['content']; + } + + /** + * @param array $options + * @author fabriceb + * @since 2009-08-21 + * @since 2011-01-25 by Antonio Ramirez + * Modified to check for correct values for specific options + */ + public function setOptions($options) + { + if(isset($options['pixelOffset'])) + { + if(!$options['pixelOffset'] instanceof EGMapSize) + throw new CException(Yii::t('EGMap', 'Property "{class}.{property}" {e}.', + array('{class}'=>get_class($this), '{property}'=>'pixelOffset','{e}'=>'must be of type EGMapSize'))); + } + if(isset($options['position'])) + { + if(!$options['position'] instanceof EGMapCoord ) + throw new CException(Yii::t('EGMap', 'Property "{class}.{property}" {e}.', + array('{class}'=>get_class($this), '{property}'=>'pixelOffset','{e}'=>'must be of type EGMapCoord'))); + } + if(isset($options['content'])){ + $this->setContent($options['content']); + unset($options['content']); + } + $this->options = array_merge($this->options,$options); + } + /** + * + * Property setter for pixelOffset + * to ensure its type + * @param EGMapSize $pixelOffset + * @author Antonio Ramirez + */ + public function setPixelOffset( EGMapSize $pixelOffset ){ + $this->options['pixelOffset'] = $pixelOffset; + } + /** + * + * Property setter position + * to ensure its type + * @param EGMapCoord $position + * @author Antonio Ramirez + */ + public function setPosition( EGMapCoord $position ){ + $this->options['position'] = $position; + } + + /** + * @param string $map_js_name + * @return string Javascript code to create the marker + * @author Fabrice Bernhard + * @since 2009-08-21 + * @since 2011-01-25 by Antonio Ramirez + * Modified options encoding + */ + public function toJs($map_js_name = 'map') + { + + $return = ''; + $return .= $this->getJsName().' = new google.maps.InfoWindow('.EGMap::encode($this->options).');'.PHP_EOL; + + foreach ($this->custom_properties as $attribute=>$value) + { + $return .= 'var '.$this->getJsName().".".$attribute." = '".$value."';".PHP_EOL; + } + foreach ($this->events as $event) + { + $return .= $event->getEventJs($this->getJsName()); + } + return $return; + } + + /** + * Adds an event listener to the marker + * + * @param EGMapEvent $event + */ + public function addEvent($event) + { + array_push($this->events,$event); + } + /** + * + * Sets custom properties to the Info Window + * @param array $custom_properties + */ + public function setCustomProperties($custom_properties) + { + if(!is_array($custom_properties)) + throw new CException(Yii::t('EGMap','EGMapInfoWindow custom properties must of type array to be set')); + $this->custom_properties=$custom_properties; + } + /** + * + * @return array custom properties + */ + public function getCustomProperties() + { + return $this->custom_properties; + } + + /** + * Sets a custom property to the generated javascript object + * + * @param string $name + * @param string $value + */ + public function setCustomProperty($name,$value) + { + $this->custom_properties[$name] = $value; + } +} diff --git a/protected/extensions/egmap/EGMapKMLService.php b/protected/extensions/egmap/EGMapKMLService.php new file mode 100644 index 0000000..c058b3d --- /dev/null +++ b/protected/extensions/egmap/EGMapKMLService.php @@ -0,0 +1,52 @@ +<?php +/** + * + * EGMapKMLService Class + * + * @link http://gmaps-samples-v3.googlecode.com/svn/trunk/latlng-to-coord-control/latlng-to-coord-control.html + * + * + * @author Antonio Ramirez Cobos + * + * + * @copyright + * + * Copyright (c) 2010 Antonio Ramirez Cobos + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +class EGMapKMLService extends EGMapBase +{ + + protected $url; + + function __construct( $url ){ + $urlValidator = new CUrlValidator(); + if($urlValidator->validateValue($url)) + $this->url = $url; + else + throw new CException( Yii::t('EGMap','EGMapKMLService.url must be a valid URL address') ); + } + + /** + * @return string Create new control to display latlng and coordinates under mouse. + */ + public function toJs( $map_js_name = 'map' ) + { + $return = 'var '.$this->getJsName().'= new google.maps.KmlLayer(\''.$this->url.'\');'.PHP_EOL; + $return .= $this->getJsName().'.setMap('.$map_js_name.');'.PHP_EOL; + return $return; + } +}
\ No newline at end of file diff --git a/protected/extensions/egmap/EGMapKeyDragZoom.php b/protected/extensions/egmap/EGMapKeyDragZoom.php new file mode 100644 index 0000000..272efa0 --- /dev/null +++ b/protected/extensions/egmap/EGMapKeyDragZoom.php @@ -0,0 +1,177 @@ +<?php +/** + * + * EGMapKeyDragZoom Class + * + * @link http://google-maps-utility-library-v3.googlecode.com/svn/tags/keydragzoom/2.0.5/docs/reference.html + * from utility library KeyDragZoom Google Maps V3 + * + * @author Antonio Ramirez Cobos + * + * + * @copyright + * + * Copyright (c) 2010 Antonio Ramirez Cobos + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +class EGMapKeyDragZoom extends EGMapBase +{ + /** + * + * key trigger definitions + * @var string + */ + const KEY_SHIFT = '"shift"'; + const KEY_ALT = '"alt"'; + /** + * + * Supported events + * @var string + */ + const EVENT_ACTIVATE = 'activate'; + const EVENT_DEACTIVATE = 'deactivate'; + const EVENT_DRAGSTART = 'dragstart'; + const EVENT_DRAG = 'drag'; + const EVENT_DRAGEND = 'dragend'; + + protected $options = array( + // An object literal or named array defining the css styles of the zoom box. The default + // is {border: "4px solid #736AFF"}. Border widths must be specified in pixel units + // (or as thin, medium, or thick). + 'boxStyle' => null, + // The hot key to hold down to activate a drag zoom, shift | ctrl | alt. The default + // is shift. NOTE: Do not use Ctrl as the hot key with Google Maps JavaScript API V3 since, + // unlike with V2, it causes a context menu to appear when running on the Macintosh. Also + // note that the alt hot key refers to the Option key on a Macintosh. + 'key' => self::KEY_SHIFT, + // An object literal or named array defining the css styles of the veil pane which covers the map when a + // drag zoom is activated. The previous name for this property was paneStyle but the use of + // this name is now deprecated. The default is {backgroundColor: "gray", opacity: 0.25, cursor: "crosshair"}. + 'veilStyle' => null, + // The name of the CSS class defining the styles for the visual control. To prevent the visual control + // from being printed, set this property to the name of a class, defined inside a @media print rule, + // which sets the CSS display style to none. + 'visualClass' => null, + // A flag indicating whether a visual control is to be used. The default is false. + 'visualEnabled' => null, + // The position of the visual control. The default position is on the left side of the map below other + // controls in the top left Ñ i.e., a position of google.maps.ControlPosition.LEFT_TOP. + 'visualPosition' => EGMapControlPosition::LEFT_TOP, + // The index of the visual control. The index is for controlling the placement of the control relative + // to other controls at the position given by visualPosition; controls with a lower index are placed + // first. Use a negative value to place the control before any default controls. No index is generally + // required; the default is null. + 'visualPositionIndex'=> null, + // The width and height values provided by this property are the offsets (in pixels) from the location + // at which the control would normally be drawn to the desired drawing location. The default is (35,0). + 'visualPositionOffset'=>null, + // The width and height values provided by this property are the size (in pixels) of each of the images + // within visualSprite. The default is (20,20). + 'visualSize'=>null, + // The URL of the sprite image used for showing the visual control in the on, off, and hot (i.e., when + // the mouse is over the control) states. The three images within the sprite must be the same size and + // arranged in on-hot-off order in a single row with no spaces between images. The default is + // http://maps.gstatic.com/mapfiles/ftr/controls/dragzoom_btn.png. + 'visualSprite'=>null, + // An object literal defining the help tips that appear when the mouse moves over the visual control. + // The off property is the tip to be shown when the control is off and the on property is the tip to be + // shown when the control is on. The default values are "Turn on drag zoom mode" and "Turn off drag zoom mode", respectively. + 'visualType'=> null + ); + /** + * + * Collection of events + * @var array + */ + protected $events = array(); + + /** + * + * Class constructor + * @param array options + */ + public function __construct( $options = array() ) + { + $this->setOptions($options); + } + /** + * + * Sets plugin options + * @param array $options + * @throws CException + */ + public function setOptions( $options ){ + if(!is_array( $options )) + throw new CException( Yii::t('EGMap', 'KeyDrEGMapKeyDragZoomagZoom options must be of type array!')); + $this->options = CMap::mergeArray($this->options, $options); + + } + public function setVeilStyle( $options ){ + if(!is_array($options)) + throw new CException(Yii::t('EGMap', 'Property "{class}.{property}" {e}.', + array('{class}'=>get_class($this), '{property}'=>'veilStyle','{e}'=>'must be of type array'))); + } + public function setBoxStyle( $options ){ + if(!is_array($options)) + throw new CException(Yii::t('EGMap', 'Property "{class}.{property}" {e}.', + array('{class}'=>get_class($this), '{property}'=>'boxStyle','{e}'=>'must be of type array'))); + } + public function setVisualSize( EGMapSize $size ){ + $this->options['visualSize'] = $size; + } + public function setVisualPositionOffset( EGMapSize $offset ){ + $this->options['visualPositionOffset'] = $offset; + } + + /** + * + * Adds an event to the plugin + * Note that the event must be a supported one + * @param string $trigger + * @param string $function + * @param boolean $encapsulate_function + * @throws CException + */ + public function addEvent( $trigger,$function,$encapsulate_function=true ){ + if( $trigger != self::EVENT_ACTIVATE && + $trigger != self::EVENT_DEACTIVATE && + $trigger != self::EVENT_DRAG && + $trigger != self::EVENT_DRAGEND && + $trigger != self::EVENT_DRAGSTART ) + throw new CException( Yii::t('EGMap', 'Unrecognized EGMapKeyDragZoom event!')); + + $this->events[] = new EGMapEvent( $trigger, $function, $encapsulate_function ); + + } + /** + * @return string Javascript code to return the Point + */ + public function toJs( $map_js_name = 'map' ) + { + foreach(array('veilStyle','boxStyle','visualClass','visualType') as $key) + if(isset($this->options[$key])) $this->options[$key] = CJavaScript::encode($this->options[$key]); + + $return = $map_js_name.'.enableKeyDragZoom('.EGMap::encode($this->options).');'; + + if (count($this->events)){ + $return .= 'var '.$this->getJsName().'='.$map_js_name.'.getDragZoomObject();'; + foreach($this->events as $e){ + $return .= $e->toJs($this->getJsName()); + } + } + return $return; + } +}
\ No newline at end of file diff --git a/protected/extensions/egmap/EGMapLatLonControl.php b/protected/extensions/egmap/EGMapLatLonControl.php new file mode 100644 index 0000000..3640305 --- /dev/null +++ b/protected/extensions/egmap/EGMapLatLonControl.php @@ -0,0 +1,43 @@ +<?php +/** + * + * EGMapLatLonControl Class + * + * @link http://gmaps-samples-v3.googlecode.com/svn/trunk/latlng-to-coord-control/latlng-to-coord-control.html + * + * + * @author Antonio Ramirez Cobos + * + * + * @copyright + * + * Copyright (c) 2010 Antonio Ramirez Cobos + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +class EGMapLatLonControl extends EGMapBase +{ + /** + * @return string Create new control to display latlng and coordinates under mouse. + */ + public function toJs( $map_js_name = 'map' ) + { + $return = 'var '.$this->getJsName().'= new LatLngControl('.$map_js_name.');'.PHP_EOL; + $return .= 'google.maps.event.addListener('.$map_js_name.', "mouseover", function(e) {'.$this->getJsName().'.set("visible", true);});'.PHP_EOL; + $return .= 'google.maps.event.addListener('.$map_js_name.', "mouseout", function(e) {'.$this->getJsName().'.set("visible", true);});'.PHP_EOL; + $return .= 'google.maps.event.addListener('.$map_js_name.', "mousemove", function(e) {'.$this->getJsName().'.updatePosition(e.latLng);});'.PHP_EOL; + return $return; + } +}
\ No newline at end of file diff --git a/protected/extensions/egmap/EGMapMarker.php b/protected/extensions/egmap/EGMapMarker.php new file mode 100644 index 0000000..ac04a40 --- /dev/null +++ b/protected/extensions/egmap/EGMapMarker.php @@ -0,0 +1,423 @@ +<?php + +/** + * + * EGMapMarker + * A GoogleMap Marker + * + * @author Antonio Ramirez + * + * @since 2010-12-22 modified by Antonio Ramirez + * + * change log: + * @since 2011-01-21 by Antonio Ramirez + * - Included support for different types of Markers + * - Implemented new and specially for EGMap modified version of CJavaScript::encode + * - Fixed logic bug on setOption function + * - Removed the need of optionsToJs function + * - Included option for global info window + * - included different types of Marker Object support + * - EGMap::encode deprecates the use of optionsToJs + * + * @TODO: modify $events to CTypeMap('EGMapEvent') + * + * + * @copyright + * info as this library is a modified version of Fabrice Bernhard + * + * Copyright (c) 2008 Fabrice Bernhard + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +class EGMapMarker extends EGMapBase { + + const DROP = 'google.maps.Animation.DROP'; + const BOUNCE = 'google.maps.Animation.BOUNCE'; + + protected $options = array( + // Map Map on which to display Marker. + 'map' => null, + // LatLng Marker position. Required. + 'position' => null, + // string Rollover text + 'title' => null, + // Icon (string | Marker Image) for the foreground + 'icon' => null, + // Shadow image + 'shadow' => null, + // Object Image map region for drag/click. Array of x/y values that define the perimeter of the icon. + 'shape' => null, + // string Mouse cursor to show on hover + 'cursor' => null, + // boolean If true, the marker can be clicked + 'clickable' => null, + // boolean If true, the marker can be dragged. + 'draggable' => null, + // If false, disables raising and lowering the marker on drag. + // This option is true by default. + 'raiseOnDrag' => null, + // boolean If true, the marker is visible + 'visible' => null, + // boolean If true, the marker shadow will not be displayed. + 'flat' => null, + // number All Markers are displayed on the map in order of their zIndex, with higher values displaying in front of Markers with lower values. By default, Markers are displayed according to their latitude, with Markers of lower latitudes appearing in front of Markers at higher latitudes. + 'zIndex' => null, + //Which animation to play when marker is added to a map. + 'animation'=>null, + ); + protected $info_window = null; + protected $info_window_shared = false; + protected $info_box = null; + protected $info_box_shared = false; + protected $events = null; + protected $custom_properties = array(); + + /** + * + * Included support for different types of Markers + * @var string marker object type (defaults to Marker) + */ + protected $marker_object = 'google.maps.Marker'; + + /** + * @param string $js_name Javascript name of the marker + * @param float $lat Latitude + * @param float $lng Longitude + * @param string $js_name name of the marker variable + * @param array $options of the marker + * @param EGmapEvent[] array of GoogleMap Events linked to the marker + * @author Fabrice Bernhard + * @since 2010-12-22 modified by Antonio Ramirez + */ + public function __construct($lat, $lng, $options = array(), $js_name='marker', $events=array()) + { + if ($js_name !== 'marker') + $this->setJsName($js_name); + + // position wont make any difference here + // as it will be set afterwards by setPosition + $this->setOptions($options); + + $this->setPosition(new EGMapCoord($lat, $lng)); + + $this->events = new CTypedList('EGMapEvent'); + + $this->setEvents($events); + } + + /** + * + * Batch set events by an array of EGMapEvents + * @param array $events + */ + public function setEvents($events) + { + if (!is_array($events)) + throw new CException(Yii::t('EGMap', 'Parameter of "{class}.{method}" {e}.', array('{class}' => get_class($this), '{method}' => 'setEvents', '{e}' => 'must be of type array'))); + if (null === $this->events) + $this->events = new CTypedList('EGMapEvent'); + + foreach ($events as $e) + { + $this->events->add($e); + } + } + + /** + * Sets the animation to the marker when it is rendered to the map + * @param string $animation + */ + public function setAnimation( $animation=self::DROP ) + { + if($animation==self::DROP || $animation==self::BOUNCE) + $this->options['animation'] = $animation; + else + $this->options['animation'] = self::DROP; + } + + /** + * Adds an event listener to the marker + * + * @param EGMapEvent $event + */ + public function addEvent(EGMapEvent $event) + { + $this->events->add($event); + } + + /** + * Construct from a EGMapGeocodedAddress object + * + * @param string $js_name + * @param EGMapGeocodedAddress $gmap_geocoded_address + * @param array $options the marker options + * @return EGMapMarker + */ + public static function constructFromGMapGeocodedAddress(EGMapGeocodedAddress $gmap_geocoded_address, $options = array(), $js_name='marker') + { + return new EGMapMarker($gmap_geocoded_address->getLat(), $gmap_geocoded_address->getLng(), $options, $js_name); + } + + /** + * @param array $options + * @author fabriceb + * @since 2009-08-21 + * @modified by Antonio Ramirez + */ + public function setOptions($options) + { + if (isset($options['title'])) + $options['title'] = CJavaScript::encode($options['title']); + + $this->options = array_merge($this->options, $options); + + // double check position + if (isset($options['position'])) + { + $this->setPosition($options['position']); + } + } + + /** + * sets the coordinates object of the marker + * + * @param EGMapCoord $position + * @author Antonio Ramirez + */ + public function setPosition(EGMapCoord $position) + { + $this->options['position'] = $position; + } + + /** + * @return float $lat Javascript latitude + * @author Antonio Ramirez + */ + public function getLat() + { + return null !== $this->options['position'] ? $this->options['position']->getLatitude() : null; + } + + /** + * @return float $lng Javascript longitude + * @author Antonio Ramirez + */ + public function getLng() + { + return null !== $this->options['position'] ? $this->options['position']->getLongitude() : null; + } + + /** + * @param string $map_js_name + * @return string Javascript code to create the marker + * @author Fabrice Bernhard + * @since 2009-08-21 + * @since 2010-12-22 modified by Antonio Ramirez + * @since 2011-01-08 modified by Antonio Ramirez + * Removed EGMapMarkerImage conversion + * @since 2011-01-11 included option for global info window + * @since 2011-01-22 included different types of Marker Object support + * EGMap::encode deprecates the use of optionsToJs + * @since 2011-01-23 fixed logic bug + * @since 2011-10-12 added info_box plugin feature + * + */ + public function toJs($map_js_name = 'map') + { + $this->options['map'] = $map_js_name; + + $return = ''; + if (null !== $this->info_window || null !== $this->info_box) + { + if ($this->info_window_shared || $this->info_box_shared) + { + $info_window_name = $map_js_name . + ($this->info_window_shared? '_info_window':'_info_box'); + + $content = $this->info_window? $this->info_window->getContent() : $this->info_box->getContent(); + + $this->addEvent( + new EGMapEvent( + 'click', + // closes automatically others opened :) + //'if (' . $info_window_name . ') ' . $info_window_name . '.close();' . PHP_EOL . + $info_window_name . '.setContent(' . $content . ');' . PHP_EOL . + $info_window_name . '.open(' . $map_js_name . ',' . $this->getJsName() . ');' . PHP_EOL + )); + } else + { + $name = $this->info_window? $this->info_window->getJsName() : $this->info_box->getJsName(); + $this->addEvent(new EGMapEvent('click', $this->info_window->getJsName() . ".open(" . $map_js_name . "," . $this->getJsName() . ");" . PHP_EOL)); + $return .= $this->info_window->toJs(); + } + } + + $return .='var ' . $this->getJsName() . ' = new ' . $this->marker_object . '(' . EGMap::encode($this->options) . ');' . PHP_EOL; + + foreach ($this->custom_properties as $attribute => $value) + { + $return .= $this->getJsName() . "." . $attribute . " = '" . $value . "';" . PHP_EOL; + } + foreach ($this->events as $event) + { + $return .= $event->getEventJs($this->getJsName()) . PHP_EOL; + } + + return $return; + } + + /** + * Adds an onlick listener that open a html window with some text + * + * @param EGMapInfoWindow $info_window + * @param boolean $shared among other markers (unique info_window display) + * + * @author Antonio Ramirez + * @since 2011-01-23 Added shared functionality for infoWindows + */ + public function addHtmlInfoWindow(EGMapInfoWindow $info_window, $shared = true) + { + $this->info_window = $info_window; + $this->info_window_shared = $shared; + $this->info_box = null; + $this->info_box_shared = false; + } + /** + * + * @return boolean if info window is shared or not + */ + public function htmlInfoWindowShared() + { + return $this->info_window_shared; + } + + /** + * @return EGMapInfoWindow + * @author Antonio Ramirez + */ + public function getHtmlInfoWindow() + { + return $this->info_window; + } + + public function addHtmlInfoBox(EGMapInfoBox $info_box, $shared = true) + { + $this->info_box = $info_box; + $this->info_box_shared = $shared; + $this->info_window = null; + $this->info_window_shared = false; + } + public function htmlInfoBoxShared() + { + return $this->info_box_shared; + } + public function getHtmlInfoBox() + { + return $this->info_box; + } + + /** + * Returns the coords code for the static version of Google Maps + * @TODO Add support for color and alpha-char + * @author Laurent Bachelier + * @return string + */ + public function getMarkerStatic() + { + + return $this->getLat() . ',' . $this->getLng(); + } + + /** + * + * Sets custom properties to the Marker + * @param array $custom_properties + */ + public function setCustomProperties($custom_properties) + { + if (!is_array($custom_properties)) + throw new CException(Yii::t('EGMap', 'EGMapMarker custom properties must of type array to be set')); + $this->custom_properties = $custom_properties; + } + + /** + * + * @return array custom properties + */ + public function getCustomProperties() + { + + return $this->custom_properties; + } + + /** + * Sets a custom property to the generated javascript object + * + * @param string $name + * @param string $value + */ + public function setCustomProperty($name, $value) + { + $this->custom_properties[$name] = $value; + } + + /** + * + * @param EGMapMarker[] $markers array of Markers + * @return EGMapCoord + * @author fabriceb + * @since 2009-05-02 + * @since 2011-01-25 modified by Antonio Ramirez + * */ + public static function getMassCenterCoord($markers) + { + $coords = array(); + foreach ($markers as $marker) + { + array_push($coords, $marker->position); + } + + return EGMapCoord::getMassCenterCoord($coords); + } + + /** + * + * @param EGMapMarker[] $markers array of MArkers + * @return EGMapCoord + * @author fabriceb + * @since 2009-05-02 + * @since 2011-01-25 modified by Antonio Ramirez + * */ + public static function getCenterCoord($markers) + { + $bounds = EGMapBounds::getBoundsContainingMarkers($markers); + + return $bounds->getCenterCoord(); + } + + /** + * + * @param EGMapBounds $gmap_bounds + * @return boolean $is_inside + * @author fabriceb + * @since Jun 2, 2009 fabriceb + */ + public function isInsideBounds(EGMapBounds $gmap_bounds) + { + + return $this->getGMapCoord()->isInsideBounds($gmap_bounds); + } + +} diff --git a/protected/extensions/egmap/EGMapMarkerClusterer.php b/protected/extensions/egmap/EGMapMarkerClusterer.php new file mode 100644 index 0000000..bc838f0 --- /dev/null +++ b/protected/extensions/egmap/EGMapMarkerClusterer.php @@ -0,0 +1,127 @@ +<?php +/** + * + * EGMapMarkerClusterer Class + * + * @link http://google-maps-utility-library-v3.googlecode.com/svn/tags/markerclusterer/1.0/docs/reference.html + * from utility library MarkerClusterer Google Maps V3 + * + * @author Antonio Ramirez Cobos + * + * + * @copyright + * + * Copyright (c) 2010 Antonio Ramirez Cobos + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +class EGMapMarkerClusterer extends EGMapBase +{ + + protected $options = array( + // The minimum number of markers to be in a cluster before the markers are hidden and a count + 'minimumClusterSize' => null, + // Wether the center of each cluster should be the average of all markers in the cluster + 'averageCenetr' => null, + // Whether the default behaviour of clicking on cluster is to zoom into it. + 'zoomOnClick' => null, + // The grid size of a cluster in pixel. Each cluster will be a square. If you want the algorithm to run faster, you can + // set this value larger. The default value is 60. + 'gridSize' => null, + // The max zoom level monitored by a marker cluster. If not given, the marker cluster assumes the maximum map zoom level. + // When maxZoom is reached or exceeded all markers will be shown without cluster. + 'maxZoom' => null, + // Custom styles for the cluster markers. The array should be ordered according to increasing cluster size, with the style + // for the smallest clusters first, and the style for the largest clusters last. + // must be an array with any of the following options: + // + // height Number Image height. + // width Number Image width. + // anchor Array of Number Anchor for label text, like [24, 12]. If not set, the text will align center and middle. + // textColor String Text color. The default value is "black". + // textSize Number Text size. + // url String Image url. + // backgroundPosition String The position of the background x, y + // + 'styles' => null + ); + /** + * + * Collection of EGMapMarkers markers + * @var array + */ + protected $markers; + + /** + * + * Class constructor + * @param array options + */ + public function __construct( $options = array() ) + { + $this->markers = new CTypedMap('EGMapMarker'); + + $this->setOptions($options); + } + + /** + * + * Sets plugin options + * @param array $options + * @throws CException + */ + public function setOptions( $options ){ + if(!is_array( $options )) + throw new CException( Yii::t('EGMap', 'EGMapMarkerClusterer options must be of type array!')); + if(isset($options['styles'])){ + $this->setStyles($options['styles']); + unset($options['styles']); + } + $this->options = array_merge($this->options, $options); + } + /** + * + * Sets a plugin option + * @param string $name option + * @param mixed $value + */ + public function setStyles( $value ){ + $this->options['styles'] = CJavaScript::encode($value); + } + /** + * + * Adds a marker to its internal collection + * @param EGMapMarker $marker + */ + public function addMarker( EGMapMarker $marker){ + + $this->markers->add($marker->getJsName(), $marker); + } + + /** + * @return string Javascript code to return the Point + */ + public function toJs( $map_js_name = 'map' ) + { + $markers = array(); + if(count($this->markers)){ + foreach($this->markers as $m) + $markers[] = $m->getJsName(); + } + $return = 'var '.$this->getJsName().'= new MarkerClusterer('.$map_js_name.','.EGMap::encode($markers).','.EGMap::encode($this->options).');'; + + return $return; + } +}
\ No newline at end of file diff --git a/protected/extensions/egmap/EGMapMarkerImage.php b/protected/extensions/egmap/EGMapMarkerImage.php new file mode 100644 index 0000000..2d8f4cd --- /dev/null +++ b/protected/extensions/egmap/EGMapMarkerImage.php @@ -0,0 +1,255 @@ +<?php + +/** + * + * EGMapMarkerImage + * + * Modified by Antonio Ramirez + * @link www.ramirezcobos.com + * + * Change log: + * @since 2011-01-22 Antonio Ramirez + * - Implemented EGMap support for object to js translation + * - Modified internal properties from arrays to objects + * - Modified all functions to work with newly adopted objects + * + * A GoogleMap MarkerImage + * @author Maxime Picaud + * + * + * @copyright + * info as this library is part of the library made by Fabrice Bernhard + * + * Copyright (c) 2008 Fabrice Bernhard + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +class EGMapMarkerImage +{ + //String $url url of image + protected $url; + + // EGMapSize + protected $size; + + // EGMapPoint + protected $origin; + + // EGMapPoint + protected $anchor; + + /** + * @param string $js_name Javascript name of the marker + * @param string $url url of image + * @param array $size array('width' => $width,'height' => $height) + * @param EGMapPoint $origin + * @param EGMapPoint $anchor + * @author Maxime Picaud + * @since 4 sept. 2009 + * @since 2011-01-21 modified by Antonio Ramirez Cobos + */ + public function __construct( $url, EGMapSize $size=null, EGMapPoint $origin=null, EGMapPoint $anchor=null) + { + $this->url = $url; + + if(null !== $size) $this->size = $size; + + if( null !== $origin) $this->origin = $origin; + + if( null !== $anchor ) $this->anchor = $anchor; + + } + + /** + * + * @return url of the image + * @author Antonio Ramirez + */ + public function getUrl() + { + return $this->url; + } + + /** + * + * @return EGMapSize | null + * @author Antonio Ramirez + */ + public function getSize() + { + return $this->size; + } + + /** + * + * @return numeric string | number size width + * @author Antonio Ramirez + */ + public function getWidth() + { + if( $this->size !== null ) + return $this->size->getWidth; + } + + /** + * + * @return numeric string |Ênumber $height + * @author Maxime Picaud + * @since 4 sept. 2009 + * @since 2011-01-22 by Antonio Ramirez + */ + public function getHeight() + { + if( $this->size !== null ) + return $this->size->getHeight; + } + + + /** + * + * @param numeric string | number $width + * @param numeric string | number $height + * @author Antonio Ramirez + * @since 2011-01-22 + */ + public function setSize($width,$height) + { + if( null === $this->size ) + $this->size = new EGMapSize(); + $this->size->setWidth($width); + $this->size->setHeight($height); + } + + /** + * + * @return EGMapPoint $anchor + * @author Maxime Picaud + * @since 4 sept. 2009 + * @since 2011-01-21 Modified by Antonio Ramirez + */ + public function getOrigin() + { + return $this->origin; + } + + /** + * + * @return numeric string | number origin CoordX + * @author Antonio Ramirez + */ + public function getOriginX() + { + if( $this->origin !== null ) + return $this->origin->getCoordX(); + + } + + /** + * + * @return numeric string | number origin CoordY + * @author Antonio Ramirez + */ + public function getOriginY() + { + if( $this->origin !== null ) + return $this->origin->getCoordY(); + } + + /** + * + * @param numeric string | number origin CoordX + * @param numeric string | number origin CoordY + * @author Antonio Ramirez + */ + public function setOrigin( $x, $y) + { + if( null === $this->origin ) + $this->origin = new EGMapPoint(); + $this->origin->setCoordX($x); + $this->origin->setCoordY($y); + } + + /** + * + * @return EGMapPoint $anchor + * @author Maxime Picaud + * @since 4 sept. 2009 + * @since 2011-01-21 Modified by Antonio Ramirez + */ + public function getAnchor() + { + return $this->anchor; + } + + /** + * + * @return numeric string | number anchor CoordX + * @author Antonio Ramirez + */ + public function getAnchorX() + { + if( $this->anchor !== null ) + return $this->anchor->getCoordX(); + } + + /** + * + * @return numeric string | number anchor CoordY + * @author Antonio Ramirez + */ + public function getAnchorY() + { + if( $this->anchor !== null ) + return $this->anchor->getCoordY(); + } + + /** + * + * @param numeric string | number anchor CoordX + * @param numeric string | number anchor CoordY + * @author Antonio Ramirez + */ + public function setAnchor($x,$y) + { + if( null === $this->anchor ) + $this->anchor = new EGMapPoint(); + $this->anchor->setCoordX($x); + $this->anchor->setCoordY($y); + } + + /** + * + * @return string js code to create the markerImage + * @author Maxime Picaud + * @since 4 sept. 2009 + * @since 2011-01-22 modified by Antonio Ramirez + * implemented EGMap support for object to + * js translation + */ + public function toJs() + { + $params = array(); + + $params[] = '"'.$this->getUrl().'"'; + $params[] = EGMap::encode($this->size); + $params[] = EGMap::encode($this->origin); + $params[] = EGMap::encode($this->anchor); + + $return = 'new google.maps.MarkerImage('.implode(',',$params).")"; + + return $return; + } + +} diff --git a/protected/extensions/egmap/EGMapMarkerWithLabel.php b/protected/extensions/egmap/EGMapMarkerWithLabel.php new file mode 100644 index 0000000..aa67b52 --- /dev/null +++ b/protected/extensions/egmap/EGMapMarkerWithLabel.php @@ -0,0 +1,147 @@ +<?php +/** + * + * EGMapMarkerWithLabel Class + * + * @author Antonio Ramirez + * @link www.ramirezcobos.com + * + * @link http://google-maps-utility-library-v3.googlecode.com/svn/tags/markerwithlabel/1.1/docs/reference.html + * from utility library MarkerWithLabel Google Maps V3 + * + * + * @copyright + * + * Copyright (c) 2011 Antonio Ramirez Cobos + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +class EGMapMarkerWithLabel extends EGMapMarker{ + + protected $label_options = array( + // By default, a label is drawn with its anchor point at (0,0) so + // that its top left corner is positioned at the anchor point of the + // associated marker. Use this property to change the anchor point of + // the label. For example, to center a 50px-wide label beneath a marker, + // specify a labelAnchor of google.maps.Point(25, 0). (Note: x-values + // increase to the right and y-values increase to the top.) + 'labelAnchor'=> null, + // The name of the CSS class defining the styles for the label. Note + // that style values for position, overflow, top, left, zIndex, display, + // marginLeft, and marginTop are ignored; these styles are for internal use only. + 'labelClass'=> null, + // The content of the label (plain text or an HTML DOM node). + 'labelContent'=> null, + // A flag indicating whether a label that overlaps its associated marker + // should appear in the background (i.e., in a plane below the marker). + // The default is false, which causes the label to appear in the foreground. + 'labelInBackGround' => null, + // An object literal whose properties define specific CSS style values to be + // applied to the label. Style values defined here override those that may be + // defined in the labelClass style sheet. If this property is changed after the + // label has been created, all previously set styles (except those defined in + // the style sheet) are removed from the label before the new style values are + // applied. Note that style values for position, overflow, top, left, zIndex, + // display, marginLeft, and marginTop are ignored; these styles are for internal use only. + 'labelStyle'=> null, + // A flag indicating whether the label is to be visible. The default is true. + // Note that even if labelVisible is true, the label will not be visible unless the + // associated marker is also visible (i.e., unless the marker's visible property is true). + 'labelVisible'=> null, + // A flag indicating whether the label and marker are to be raised when the marker is dragged. + // The default is true. If a draggable marker is being created and a version of Google + // Maps API earlier than V3.3 is being used, this property must be set to false. + 'raiseOnDrag'=>null + + ); + /** + * @param string $js_name Javascript name of the marker + * @param float $lat Latitude + * @param float $lng Longitude + * @param EGMapIcon $icon + * @param EGmapEvent[] array of GoogleMap Events linked to the marker + * @author Antonio Ramirez + */ + public function __construct( $lat, $lng, $options = array(), $js_name='marker',$events=array() ) + { + $this->marker_object = 'MarkerWithLabel'; + + $options = array_merge($this->label_options, $this->encodeOptions($options)); + + parent::__construct( $lat, $lng, $options, $js_name, $events ); + + } + /** + * + * Sets the anchor of the label + * @param EGMapPoint $anchor + */ + public function setLabelAnchor( EGMapPoint $anchor ){ + + $this->options['labelAnchor'] = $anchor; + } + /** + * + * Sets the label HTML content + * @param string $content + */ + public function setLabelContent( $content ){ + + $this->options['labelContent']='"'.$content.'"'; + } + /** + * + * Set the style class name for the label + * @param unknown_type $class + */ + public function setLabelClass( $class ){ + + $this->options['labelClass'] = '"'.$class.'"'; + + } + /** + * + * Sets label style + * position, overflow, top, left, zIndex, + * display, marginLeft, and marginTop are ignored + * @param array $styleOptions + * @throws CException + */ + public function setLabelStyle( $styleOptions ){ + if(!is_array( $styleOptions )) + throw new CException( Yii::t('EGMap', 'EGMapMarkerWithLabel label style options must be of type array!')); + $this->options['labelStyle'] = CJavaScript::encode($styleOptions); + } + /** + * (non-PHPdoc) + * @see EGMapMarker::setOptions() + */ + public function setOptions( $options ){ + parent::setOptions( $this->encodeOptions($options) ); + } + /** + * + * Encodes options appropiatelly + * @param array $options + */ + private function encodeOptions( $options ){ + if(!is_array( $options )) + throw new CException( Yii::t('EGMap', 'EGMapMarkerWithLabel.encodeOptions parameter must be of type array!')); + foreach(array('labelContent', 'labelClass', 'labelStyle') as $key ) + if(isset($options[$key])) $options[$key] = CJavaScript::encode($options[$key]); + + return $options; + } +} diff --git a/protected/extensions/egmap/EGMapPoint.php b/protected/extensions/egmap/EGMapPoint.php new file mode 100644 index 0000000..e98522c --- /dev/null +++ b/protected/extensions/egmap/EGMapPoint.php @@ -0,0 +1,89 @@ +<?php +/** + * + * EGMapPoint Class + * + * @author Antonio Ramirez Cobos + * @link www.ramirezcobos.com + * + * + * @copyright + * + * Copyright (c) 2010 Antonio Ramirez Cobos + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +class EGMapPoint { + + /** + * + * X coordenate + * @var integer x + */ + private $_x; + /** + * + * Y coordenate + * @var integer y + */ + private $_y; + /** + * + * Class constructor + * @param integer $x + * @param integer $y + */ + public function __construct( $x=0, $y=0 ) + { + $this->setCoordX($x); + $this->setCoordY($y); + } + /** + * + * Sets X coordenate of the point + * @param integer $x + */ + public function setCoordX( $x ){ + if( !is_numeric($x) ) + throw new CException(Yii::t('EGMap','X Coordenate must be a numeric string or a number!')); + + $this->_x = $x; + } + /** + * + * Sets Y coordenate of the point + * @param integer $y + */ + public function setCoordY( $y ){ + if( !is_numeric($y) ) + throw new CException(Yii::t('EGMap','Y Coordenate must be a numeric string or a number!')); + + $this->_y = $y; + } + /** + * + * returns array representation of the coords + */ + public function toArray(){ + return array('x'=>$this->_x, 'y'=>$this->_y); + } + /** + * @return string Javascript code to return the Point + */ + public function toJs() + { + return ' new google.maps.Point('.$this->_x.','.$this->_y.')'; + } +}
\ No newline at end of file diff --git a/protected/extensions/egmap/EGMapPolygon.php b/protected/extensions/egmap/EGMapPolygon.php new file mode 100644 index 0000000..6b943c7 --- /dev/null +++ b/protected/extensions/egmap/EGMapPolygon.php @@ -0,0 +1,328 @@ +<?php + +/** + * + * EGMapPolygon + * A GoogleMap Polygon + * + * @author Matt Kay + * + * @since 2011-03-10 + * Added this class based on EGMapMarker + * @TODO: look at event + * @TODO: get static version of an overlay (polygon) + * @TODO: modify $events to CTypeMap('EGMapEvent') (originates from EGMapMarker) + * + * + * @copyright + * + * Copyright (c) 2010 Antonio Ramirez - Matt Kay + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +class EGMapPolygon extends EGMapBase { + + protected $options = array( + // coordinates of the polygon + 'paths' => null, + // stroke color of the edge of the polygon + 'strokeColor' => '"#FF0000"', + //stroke opacity of the edge of the polygon + 'strokeOpacity' => 0.8, + //stroke weight of the edge of the polygon + 'strokeWeight' => 2, + //fill color of the polygon + 'fillColor' => '"#FF0000"', + //fill opacity of the polygon + 'fillOpacity' => 0.35 + ); + protected $info_window = null; + protected $info_window_shared = false; + protected $events = null; + protected $custom_properties = array(); + protected $polygon_object = 'google.maps.Polygon'; + + /** + * @param string $js_name Javascript name of the polygon + * @param EGMapCoord[] array coordinates of the polygon + * @param string $js_name name of the polygon variable + * @param array $options of the polygon + * @param EGmapEvent[] array of GoogleMap Events linked to the polygon + * @author Matt Kay + */ + public function __construct($coords, $options = array(), $js_name='polygon', $events=array()) + { + if ($js_name !== 'polygon') + $this->setJsName($js_name); + + // coords wont make any difference here + // as it will be set afterwards by setCoords + $this->setOptions($options); + + $this->setCoords($coords); + + $this->events = new CTypedList('EGMapEvent'); + + $this->setEvents($events); + } + + /** + * + * Batch set events by an array of EGMapEvents + * @param array $events + */ + public function setEvents($events) + { + if (!is_array($events)) + throw new CException(Yii::t('EGMap', 'Parameter of "{class}.{method}" {e}.', array('{class}' => get_class($this), '{method}' => 'setEvents', '{e}' => 'must be of type array'))); + if (null === $this->events) + $this->events = new CTypedList('EGMapEvent'); + + foreach ($events as $e) + { + $this->events->add($e); + } + } + + /** + * Adds an event listener to the marker + * + * @param EGMapEvent $event + */ + public function addEvent(EGMapEvent $event) + { + $this->events->add($event); + } + + /** + * @param array $options + * @author fabriceb + * @since 2011-03-10 + * modified for EGMapPolygon by Matt Kay + */ + public function setOptions($options) + { + + $this->options = array_merge($this->options, $options); + } + + /** + * gets the coordinates of the polygon + * + * @param EGMapCoord[] $polygon_coords + * @author Matt Kay + */ + public function getCoords() + { + return $this->options['paths']; + } + + /** + * sets the coordinates of the polygon + * + * @param EGMapCoord[] $polygon_coords + * @author Matt Kay + */ + public function setCoords($coords) + { + $tmp = array(); + // go through array to check for valid EGMapCoord objects + foreach ($coords as $coord) + { + if (is_a($coord, 'EGMapCoord')) + { + $tmp[] = $coord; + } + } + // throw Exception when number of coords is not sufficient for desribing a polygon + if (sizeof($tmp) < 3) + { + throw new CException(Yii::t('EGMapPolygon', 'EGMapPolygon argument #1 has to be an array of minimum three EGMapCoord objects.')); + } + $this->options['paths'] = $tmp; + } + /** + * + * Return center of bounds + */ + public function getCenterOfBounds() + { + return EGMapBounds::getBoundsContainingPolygons(array($this))->getCenterCoord(); + } + /** + * @param string $map_js_name + * @return string Javascript code to create the polygon + * @author Matt Kay + * @since 2011-03-10 + * Added this method based on the one in the class EGMapMarker + * @since 2011-16-12 + * Added Info window support + */ + public function toJs($map_js_name = 'map') + { + $this->options['map'] = $map_js_name; + + $return = ''; + if (null !== $this->info_window) + { + if ($this->info_window_shared) + { + $info_window_name = $map_js_name . '_info_window'; + $this->addEvent( + new EGMapEvent( + 'click', + 'if (' . $info_window_name . ') ' . $info_window_name . '.close();' . PHP_EOL . + $info_window_name . ' = ' . $this->info_window->getJsName() . ';' . PHP_EOL . + $info_window_name . ".setPosition(" . $this->getCenterOfBounds()->toJs() . ");" . PHP_EOL . + $info_window_name . ".open(" . $map_js_name . ");" . PHP_EOL + )); + } + else + $this->addEvent(new EGMapEvent('click', + $this->info_window->getJsName() . ".setPosition(" . $this->getCenterOfBounds()->toJs() . ");" . PHP_EOL . + $this->info_window->getJsName() . ".open(" . $map_js_name . ");" . PHP_EOL + )); + $return .= $this->info_window->toJs(); + } + + $return .='var ' . $this->getJsName() . ' = new ' . $this->polygon_object . '(' . EGMap::encode($this->options) . ');' . PHP_EOL; + foreach ($this->custom_properties as $attribute => $value) + { + $return .= $this->getJsName() . "." . $attribute . " = '" . $value . "';" . PHP_EOL; + } + foreach ($this->events as $event) + { + $return .= $event->getEventJs($this->getJsName()) . PHP_EOL; + } + + $return .= $this->getJsName() . '.setMap(' . $map_js_name . ');'; + + return $return; + } + + /** + * Adds an onlick listener that open a html window with some text + * + * @param EGMapInfoWindow $info_window + * @param boolean $shared among other markers (unique info_window display) + * + * @author Antonio Ramirez + * @since 2011-01-23 Added shared functionality for infoWindows + */ + public function addHtmlInfoWindow(EGMapInfoWindow $info_window, $shared = true) + { + $this->info_window = $info_window; + $this->info_window_shared = $shared; + } + + /** + * + * @return boolean if info window is shared or not + */ + public function htmlInfoWindowShared() + { + return $this->info_window_shared; + } + + /** + * @return EGMapInfoWindow + * @author Antonio Ramirez + */ + public function getHtmlInfoWindow() + { + return $this->info_window; + } + + /** + * + * Sets custom properties to the Marker + * @param array $custom_properties + */ + public function setCustomProperties($custom_properties) + { + if (!is_array($custom_properties)) + throw new CException(Yii::t('EGMap', 'EGMapMarker custom properties must of type array to be set')); + $this->custom_properties = $custom_properties; + } + + /** + * + * @return array custom properties + */ + public function getCustomProperties() + { + + return $this->custom_properties; + } + + /** + * Sets a custom property to the generated javascript object + * + * @param string $name + * @param string $value + */ + public function setCustomProperty($name, $value) + { + $this->custom_properties[$name] = $value; + } + + /** + * + * @param EGMapMarker[] $markers array of Markers + * @return EGMapCoord + * @author fabriceb + * @since 2009-05-02 + * @since 2011-01-25 modified by Antonio Ramirez + * */ + public static function getMassCenterCoord($markers) + { + $coords = array(); + foreach ($markers as $marker) + { + array_push($coords, $marker->position); + } + + return EGMapCoord::getMassCenterCoord($coords); + } + + /** + * + * @param EGMapMarker[] $markers array of MArkers + * @return EGMapCoord + * @author fabriceb + * @since 2009-05-02 + * @since 2011-01-25 modified by Antonio Ramirez + * */ + public static function getCenterCoord($polygons) + { + $bounds = EGMapBounds::getBoundsContainingPolygons($polygons); + + return $bounds->getCenterCoord(); + } + + /** + * + * @param EGMapBounds $gmap_bounds + * @return boolean $is_inside + * @author fabriceb + * @since Jun 2, 2009 fabriceb + */ + public function isInsideBounds(EGMapBounds $gmap_bounds) + { + + return $this->getGMapCoord()->isInsideBounds($gmap_bounds); + } + +} diff --git a/protected/extensions/egmap/EGMapPolylineEncoder.php b/protected/extensions/egmap/EGMapPolylineEncoder.php new file mode 100644 index 0000000..23b2824 --- /dev/null +++ b/protected/extensions/egmap/EGMapPolylineEncoder.php @@ -0,0 +1,248 @@ +<?php +/** + * EGMapPolylineEncoder + * + * Modified version of: + * PolylineEncoder based on Mark McClure's Javascript PolylineEncoder + * and Jim Hribar's PHP version. All nicely melted into a proper PHP5 class. + * + * @package Google Maps Helpers + * @since 2008-12-02 + * @author Matthias Bauer <matthias@pulpmedia.at> + * @copyright 2008, Pulpmedia Medientechnik und -design GmbH + * @see http://facstaff.unca.edu/mcmcclur/GoogleMaps/EncodePolyline/ + */ +class EGMapPolylineEncoder { + + protected $numLevels = 18; + protected $zoomFactor = 2; + protected $verySmall = 0.00001; + protected $forceEndpoints = true; + protected $zoomLevelBreaks = array(); + + /** + * All parameters are set with useful defaults. + * If you actually want to understand them, see Mark McClure's detailed description. + * + * @see http://facstaff.unca.edu/mcmcclur/GoogleMaps/EncodePolyline/algorithm.html + */ + public function __construct($numLevels = 18, $zoomFactor = 2, $verySmall = 0.00001, $forceEndpoints = true) + { + $this->numLevels = $numLevels; + $this->zoomFactor = $zoomFactor; + $this->verySmall = $verySmall; + $this->forceEndpoints = $forceEndpoints; + + for ($i = 0; $i < $this->numLevels; $i++) + { + $this->zoomLevelBreaks[$i] = $this->verySmall * pow($this->zoomFactor, $this->numLevels - $i - 1); + } + } + + /** + * Generates all values needed for the encoded Google Maps Polyline. + * + * @param array Multidimensional input array in the form of + * array(array(latitude, longitude), array(latitude, longitude),...) + * + * @return String the encoded points | stdClass Simple object containing three public parameter: + * - points: the points string with escaped backslashes + * - levels: the encoded levels ready to use + * - rawPoints: the points right out of the encoder + * - numLevels: should be used for creating the polyline + * - zoomFactor: should be used for creating the polyline + */ + public function encode($points, $pointsOnly = true) + { + $absMaxDist=0; + $dists = array(); + if (count($points) > 2) + { + $stack[] = array(0, count($points) - 1); + while (count($stack) > 0) + { + $current = array_pop($stack); + $maxDist = 0; + for ($i = $current[0] + 1; $i < $current[1]; $i++) + { + $temp = $this->distance($points[$i], $points[$current[0]], $points[$current[1]]); + if ($temp > $maxDist) + { + $maxDist = $temp; + $maxLoc = $i; + if ($maxDist > $absMaxDist) + { + $absMaxDist = $maxDist; + } + } + } + if ($maxDist > $this->verySmall) + { + $dists[$maxLoc] = $maxDist; + array_push($stack, array($current[0], $maxLoc)); + array_push($stack, array($maxLoc, $current[1])); + } + } + } + + if ($pointsOnly) + return str_replace("\\","\\\\", $this->createEncodings($points, $dists)); + + $polyline = new stdClass(); + $polyline->rawPoints = $this->createEncodings($points, $dists); + $polyline->levels = $this->encodeLevels($points, $dists, $absMaxDist); + $polyline->points = str_replace("\\", "\\\\", $polyline->rawPoints); + $polyline->numLevels = $this->numLevels; + $polyline->zoomFactor = $this->zoomFactor; + + return $polyline; + } + /** + * + * @param integer $dd + * @return integer the computed level + */ + private function computeLevel($dd) + { + if ($dd > $this->verySmall) + { + $lev = 0; + while ($dd < $this->zoomLevelBreaks[$lev]) + { + $lev++; + } + } + return $lev; + } + /** + * Calculates distance between point locations + * + * @param integer $p0 + * @param integer $p1 + * @param integer $p2 + * @return integer + */ + private function distance($p0, $p1, $p2) + { + if ($p1[0] == $p2[0] && $p1[1] == $p2[1]) + { + $out = sqrt(pow($p2[0] - $p0[0], 2) + pow($p2[1] - $p0[1], 2)); + } else + { + $u = (($p0[0] - $p1[0]) * ($p2[0] - $p1[0]) + ($p0[1] - $p1[1]) * ($p2[1] - $p1[1])) / (pow($p2[0] - $p1[0], 2) + pow($p2[1] - $p1[1], 2)); + if ($u <= 0) + { + $out = sqrt(pow($p0[0] - $p1[0], 2) + pow($p0[1] - $p1[1], 2)); + } + if ($u >= 1) + { + $out = sqrt(pow($p0[0] - $p2[0], 2) + pow($p0[1] - $p2[1], 2)); + } + if (0 < $u && $u < 1) + { + $out = sqrt(pow($p0[0] - $p1[0] - $u * ($p2[0] - $p1[0]), 2) + pow($p0[1] - $p1[1] - $u * ($p2[1] - $p1[1]), 2)); + } + } + return $out; + } + /** + * Encodes a signed number + * + * @param float $num + * @return string + */ + private function encodeSignedNumber($num) + { + $sgn_num = $num << 1; + if ($num < 0) + { + $sgn_num = ~($sgn_num); + } + return $this->encodeNumber($sgn_num); + } + /** + * Encodes points + * @param array $points + * @param array $dists + * @return string the encoded points + */ + private function createEncodings($points, $dists) + { + $encoded_points = ''; + + $plat = $lng = $plng = $plat = 0; + for ($i = 0; $i < count($points); $i++) + { + if (isset($dists[$i]) || $i == 0 || $i == count($points) - 1) + { + $point = $points[$i]; + $lat = $point[0]; + $lng = $point[1]; + $late5 = floor($lat * 1e5); + $lnge5 = floor($lng * 1e5); + $dlat = $late5 - $plat; + $dlng = $lnge5 - $plng; + $plat = $late5; + $plng = $lnge5; + $encoded_points .= $this->encodeSignedNumber($dlat) . $this->encodeSignedNumber($dlng); + } + } + return $encoded_points; + } + /** + * Encodes levels + * + * @param array $points + * @param array $dists + * @param integer $absMaxDist + * @return string + */ + private function encodeLevels($points, $dists, $absMaxDist) + { + $encoded_levels = ''; + + if ($this->forceEndpoints) + { + $encoded_levels .= $this->encodeNumber($this->numLevels - 1); + } else + { + $encoded_levels .= $this->encodeNumber($this->numLevels - $this->computeLevel($absMaxDist) - 1); + } + for ($i = 1; $i < count($points) - 1; $i++) + { + if (isset($dists[$i])) + { + $encoded_levels .= $this->encodeNumber($this->numLevels - $this->computeLevel($dists[$i]) - 1); + } + } + if ($this->forceEndpoints) + { + $encoded_levels .= $this->encodeNumber($this->numLevels - 1); + } else + { + $encoded_levels .= $this->encodeNumber($this->numLevels - $this->computeLevel($absMaxDist) - 1); + } + return $encoded_levels; + } + /** + * Encodes a number + * + * @param integer $num + * @return string + */ + private function encodeNumber($num) + { + $encodeString = ''; + + while ($num >= 0x20) + { + $nextValue = (0x20 | ($num & 0x1f)) + 63; + $encodeString .= chr($nextValue); + $num >>= 5; + } + $finalValue = $num + 63; + $encodeString .= chr($finalValue); + return $encodeString; + } + +} diff --git a/protected/extensions/egmap/EGMapRectangle.php b/protected/extensions/egmap/EGMapRectangle.php new file mode 100644 index 0000000..7ac9f1f --- /dev/null +++ b/protected/extensions/egmap/EGMapRectangle.php @@ -0,0 +1,253 @@ +<?php + +/** + * + * EGMapRectangle + * A GoogleMap Rectangle + * + * @author Antonio Ramirez Cobos + * + * Example: + * + * $bounds = new EGMapBounds(new EGMapCoord(25.774252, -80.190262),new EGMapCoord(32.321384, -64.75737) ); + * $rec = new EGMapRectangle($bounds); + * $rec->addHtmlInfoWindow(new EGMapInfoWindow('Hey! I am a rectangle!')); + * $gMap->addRectangle($rec); + * + * + * @copyright + * + * Copyright (c) 2011 Antonio Ramirez + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +class EGMapRectangle extends EGMapBase { + + protected $options = array( + // LatLngBounds The bounds. + 'bounds' => null, // EGMapBounds + // Indicates whether this Rectangle handles click events. Defaults to true. + 'clickable' => true, + // Map on which to display Circle. + 'map' => null, + // stroke color of the edge of the rectangle + 'strokeColor' => '"#FF0000"', + //stroke opacity of the edge of the rectangle + 'strokeOpacity' => 0.8, + //stroke weight of the edge of the rectangle + 'strokeWeight' => 2, + //fill color of the rectangle + 'fillColor' => '"#FF0000"', + //fill opacity of the rectangle + 'fillOpacity' => 0.35, + 'zIndex' => 0 + ); + + /** + * + * Info window object attached to the object + * @var EGMapInfoWindow + */ + protected $info_window = null; + + /** + * + * If the Info window is shared or not + * @var boolean + */ + protected $info_window_shared = false; + + /** + * + * Events attached to the object + * @var array + */ + protected $events = null; + + /** + * + * google maps js object name + * @var string + */ + protected $rectangle_object = 'google.maps.Rectangle'; + + /** + * + * @param EGMapBounds bounds coordinates of the rectangle + * @param string $js_name name of the rectangle variable + * @param array $options of the rectangle + * @param EGmapEvent[] array of GoogleMap Events linked to the rectangle + * @author Antonio Ramirez + */ + public function __construct(EGMapBounds $bounds, $options = array(), $js_name='rectangle', $events=array()) + { + if ($js_name !== 'rectangle') + $this->setJsName($js_name); + + $this->setOptions($options); + + $this->setBounds($bounds); + + $this->events = new CTypedList('EGMapEvent'); + + $this->setEvents($events); + } + + /** + * + * Batch set events by an array of EGMapEvents + * @param array $events + */ + public function setEvents($events) + { + if (!is_array($events)) + throw new CException(Yii::t('EGMap', 'Parameter of "{class}.{method}" {e}.', array('{class}' => get_class($this), '{method}' => 'setEvents', '{e}' => 'must be of type array'))); + if (null === $this->events) + $this->events = new CTypedList('EGMapEvent'); + + foreach ($events as $e) + { + $this->events->add($e); + } + } + + /** + * Adds an event listener to the marker + * + * @param EGMapEvent $event + */ + public function addEvent(EGMapEvent $event) + { + $this->events->add($event); + } + + /** + * @param array $options + * @author Antonio Ramirez + */ + public function setOptions($options) + { + + $this->options = array_merge($this->options, $options); + } + + /** + * gets the bounds of the rectangle + * + * @return EGMapBounds | null $bounds + * @author Antonio Ramirez + */ + public function getBounds() + { + return $this->options['bounds']; + } + + /** + * sets the bounds coordinates of the rectangle + * + * @param EGMapBounds $bounds + * @author Antonio Ramirez Cobos + */ + public function setBounds(EGMapBounds $bounds) + { + $this->options['bounds'] = $bounds; + } + + /** + * + * Return center of bounds + */ + public function getCenterOfBounds() + { + if (null !== $this->getBounds() && $this->getBounds() instanceof EGMapBounds) + return $this->getBounds()->getCenterCoord(); + return null; + } + + /** + * @param string $map_js_name + * @return string Javascript code to create the rectangle + * @author Antonio Ramirez + */ + public function toJs($map_js_name = 'map') + { + $this->options['map'] = $map_js_name; + + $return = ''; + if (null !== $this->info_window) + { + if ($this->info_window_shared) + { + $info_window_name = $map_js_name . '_info_window'; + $this->addEvent( + new EGMapEvent( + 'click', + 'if (' . $info_window_name . ') ' . $info_window_name . '.close();' . PHP_EOL . + $info_window_name . ' = ' . $this->info_window->getJsName() . ';' . PHP_EOL . + $info_window_name . ".setPosition(" . $this->getCenterOfBounds()->toJs() . ");" . PHP_EOL . + $info_window_name . ".open(" . $map_js_name . ");" . PHP_EOL + )); + } + else + $this->addEvent(new EGMapEvent('click', + $this->info_window->getJsName() . ".setPosition(" . $this->getCenterOfBounds()->toJs() . ");" . PHP_EOL . + $this->info_window->getJsName() . ".open(" . $map_js_name . ");" . PHP_EOL + )); + $return .= $this->info_window->toJs(); + } + + $return .='var ' . $this->getJsName() . ' = new ' . $this->rectangle_object . '(' . EGMap::encode($this->options) . ');' . PHP_EOL; + + foreach ($this->events as $event) + { + $return .= $event->getEventJs($this->getJsName()) . PHP_EOL; + } + + return $return; + } + + /** + * Adds an onlick listener that open a html window with some text + * + * @param EGMapInfoWindow $info_window + * @param boolean $shared among other markers (unique info_window display) + * + * @author Antonio Ramirez + */ + public function addHtmlInfoWindow(EGMapInfoWindow $info_window, $shared = true) + { + $this->info_window = $info_window; + $this->info_window_shared = $shared; + } + + /** + * + * @return boolean if info window is shared or not + */ + public function htmlInfoWindowShared() + { + return $this->info_window_shared; + } + + /** + * @return EGMapInfoWindow + * @author Antonio Ramirez + */ + public function getHtmlInfoWindow() + { + return $this->info_window; + } + +} diff --git a/protected/extensions/egmap/EGMapSize.php b/protected/extensions/egmap/EGMapSize.php new file mode 100644 index 0000000..4a6dd22 --- /dev/null +++ b/protected/extensions/egmap/EGMapSize.php @@ -0,0 +1,91 @@ +<?php +/** + * + * EGMapSize Class + * + * Two-dimensonal size, where width is the distance on the x-axis, and height is the distance on the y-axis. + * + * @author Antonio Ramirez Cobos + * @link www.ramirezcobos.com + * + * + * @copyright + * + * Copyright (c) 2010 Antonio Ramirez Cobos + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +class EGMapSize { + + /** + * + * The height along the y-axis, in pixels. + * @var integer height + */ + private $_height; + /** + * + * The width along the x-axis, in pixels. + * @var integer width + */ + private $_width; + /** + * + * Class constructor + * @param integer $height + * @param integer $width + */ + public function __construct( $height=0, $width=0 ) + { + $this->setHeight($height); + $this->setWidth($width); + } + /** + * + * Sets Height of the Size + * @param integer $height + */ + public function setHeight( $height ){ + if( !is_numeric($height) ) + throw new CException(Yii::t('EGMap','Height must be a numeric string or a number!')); + + $this->_height = $height; + } + /** + * + * Sets the Width of the Size + * @param integer $width + */ + public function setWidth( $width ){ + if( !is_numeric($width) ) + throw new CException(Yii::t('EGMap','Width must be a numeric string or a number!')); + + $this->_width = $width; + } + /** + * + * returns array representation of the size + */ + public function toArray(){ + return array('width'=>$this->_width, 'height'=>$this->_height); + } + /** + * @return string Javascript code to return the Size + */ + public function toJs() + { + return ' new google.maps.Size('.$this->_width.','.$this->_height.')'; + } +}
\ No newline at end of file diff --git a/protected/extensions/egmap/assets/geoxml3.js b/protected/extensions/egmap/assets/geoxml3.js new file mode 100644 index 0000000..58b4cd1 --- /dev/null +++ b/protected/extensions/egmap/assets/geoxml3.js @@ -0,0 +1,1018 @@ +/* + geoxml3.js + + Renders KML on the Google Maps JavaScript API Version 3 + http://code.google.com/p/geoxml3/ + + Copyright 2010 Sterling Udell, Larry Ross + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +// Extend the global String object with a method to remove leading and trailing whitespace +if (!String.prototype.trim) { + String.prototype.trim = function () { + return this.replace(/^\s+|\s+$/g, ''); + }; +} + +// Declare namespace +geoXML3 = window.geoXML3 || {instances: []}; + +// Constructor for the root KML parser object +geoXML3.parser = function (options) { + // Private variables + var parserOptions = geoXML3.combineOptions(options, { + singleInfoWindow: false, + processStyles: true, + zoom: true + }); + var docs = []; // Individual KML documents + var lastPlacemark; + var parserName; + if (!parserOptions.infoWindow && parserOptions.singleInfoWindow) + parserOptions.infoWindow = new google.maps.InfoWindow(); + // Private methods + + var parse = function (urls, docSet) { + // Process one or more KML documents + if (!parserName) { + parserName = 'geoXML3.instances[' + (geoXML3.instances.push(this) - 1) + ']'; + } + + if (typeof urls === 'string') { + // Single KML document + urls = [urls]; + } + + // Internal values for the set of documents as a whole + var internals = { + parser: this, + docSet: docSet || [], + remaining: urls.length, + parseOnly: !(parserOptions.afterParse || parserOptions.processStyles) + }; + var thisDoc, j; + for (var i = 0; i < urls.length; i++) { + var baseUrl = urls[i].split('?')[0]; + for (j = 0; j < docs.length; j++) { + if (baseUrl === docs[j].baseUrl) { + // Reloading an existing document + thisDoc = docs[j]; + thisDoc.url = urls[i]; + thisDoc.internals = internals; + thisDoc.reload = true; + docs.splice(j, 1); + break; + } + } + thisDoc = thisDoc || { + url: urls[i], + baseUrl: baseUrl, + internals: internals + }; + internals.docSet.push(thisDoc); + geoXML3.fetchXML(thisDoc.url, function (responseXML) {render(responseXML, thisDoc);}); + } + }; + + var hideDocument = function (doc) { + if (!doc) doc = docs[0]; + // Hide the map objects associated with a document + var i; + if (!!doc.markers) { + for (i = 0; i < doc.markers.length; i++) { + if(!!doc.markers[i].infoWindow) doc.markers[i].infoWindow.close(); + doc.markers[i].setVisible(false); + } + } + if (!!doc.ggroundoverlays) { + for (i = 0; i < doc.ggroundoverlays.length; i++) { + doc.ggroundoverlays[i].setOpacity(0); + } + } + if (!!doc.gpolylines) { + for (i=0;i<doc.gpolylines.length;i++) { + doc.gpolylines[i].setMap(null); + } + } + if (!!doc.gpolygons) { + for (i=0;i<doc.gpolygons.length;i++) { + doc.gpolygons[i].setMap(null); + } + } + }; + + var showDocument = function (doc) { + if (!doc) doc = docs[0]; + // Show the map objects associated with a document + var i; + if (!!doc.markers) { + for (i = 0; i < doc.markers.length; i++) { + doc.markers[i].setVisible(true); + } + } + if (!!doc.ggroundoverlays) { + for (i = 0; i < doc.ggroundoverlays.length; i++) { + doc.ggroundoverlays[i].setOpacity(doc.ggroundoverlays[i].percentOpacity_); + } + } + if (!!doc.gpolylines) { + for (i=0;i<doc.gpolylines.length;i++) { + doc.gpolylines[i].setMap(parserOptions.map); + } + } + if (!!doc.gpolygons) { + for (i=0;i<doc.gpolygons.length;i++) { + doc.gpolygons[i].setMap(parserOptions.map); + } + } + }; + +function processStyle(thisNode, styles, styleID) { + var nodeValue = geoXML3.nodeValue; + var defaultStyle = { + color: "ff000000", // black + width: 1, + fill: true, + outline: true, + fillcolor: "3fff0000" // blue + }; + styles[styleID] = styles[styleID] || defaultStyle; + var styleNodes = thisNode.getElementsByTagName('Icon'); + if (!!styleNodes && !!styleNodes.length && (styleNodes.length > 0)) { + styles[styleID] = { + href: nodeValue(styleNodes[0].getElementsByTagName('href')[0]), + scale: nodeValue(styleNodes[0].getElementsByTagName('scale')[0]) + }; + if (!isNaN(styles[styleID].scale)) styles[styleID].scale = 1.0; + } + styleNodes = thisNode.getElementsByTagName('LineStyle'); + if (!!styleNodes && !!styleNodes.length && (styleNodes.length > 0)) { + styles[styleID].color = nodeValue(styleNodes[0].getElementsByTagName('color')[0]), + styles[styleID].width = nodeValue(styleNodes[0].getElementsByTagName('width')[0]) + } + styleNodes = thisNode.getElementsByTagName('PolyStyle'); + if (!!styleNodes && !!styleNodes.length && (styleNodes.length > 0)) { + styles[styleID].outline = getBooleanValue(styleNodes[0].getElementsByTagName('outline')[0]); + styles[styleID].fill = getBooleanValue(styleNodes[0].getElementsByTagName('fill')[0]); + styles[styleID].fillcolor = nodeValue(styleNodes[0].getElementsByTagName('color')[0]); + } + return styles[styleID]; +} + +function getBooleanValue(node) { + var nodeContents = geoXML3.nodeValue(node); + if (!nodeContents) return true; + if (nodeContents) nodeContents = parseInt(nodeContents); + if (isNaN(nodeContents)) return true; + if (nodeContents == 0) return false; + else return true; +} + +function processPlacemarkCoords(node, tag) { + var parent = node.getElementsByTagName(tag); +var coordListA = []; + for (var i=0; i<parent.length; i++) { + var coordNodes = parent[i].getElementsByTagName('coordinates') + if (!coordNodes) { + if (coordListA.length > 0) { + break; + } else { + return [{coordinates: []}]; + } + } + + for (var j=0; j<coordNodes.length;j++) { + var coords = geoXML3.nodeValue(coordNodes[j]).trim(); + coords = coords.replace(/,\s+/g, ','); + var path = coords.split(/\s+/g); + var pathLength = path.length; + var coordList = []; + for (var k = 0; k < pathLength; k++) { + coords = path[k].split(','); + coordList.push({ + lat: parseFloat(coords[1]), + lng: parseFloat(coords[0]), + alt: parseFloat(coords[2]) + }); + } + coordListA.push({coordinates: coordList}); + } +} + return coordListA; +} + + var render = function (responseXML, doc) { + // Callback for retrieving a KML document: parse the KML and display it on the map + if (!responseXML) { + // Error retrieving the data + geoXML3.log('Unable to retrieve ' + doc.url); + if (parserOptions.failedParse) { + parserOptions.failedParse(doc); + } + } else if (!doc) { + throw 'geoXML3 internal error: render called with null document'; + } else { //no errors + var i; + var styles = {}; + doc.placemarks = []; + doc.groundoverlays = []; + doc.ggroundoverlays = []; + doc.networkLinks = []; + doc.gpolygons = []; + doc.gpolylines = []; + + // Declare some helper functions in local scope for better performance + var nodeValue = geoXML3.nodeValue; + + // Parse styles + var styleID, styleNodes; + nodes = responseXML.getElementsByTagName('Style'); + nodeCount = nodes.length; + for (i = 0; i < nodeCount; i++) { + thisNode = nodes[i]; + var thisNodeId = thisNode.getAttribute('id'); + if (!!thisNodeId) { + styleID = '#' + thisNodeId; + processStyle(thisNode, styles, styleID); + } + } + doc.styles = styles; + if (!!parserOptions.processStyles || !parserOptions.createMarker) { + // Convert parsed styles into GMaps equivalents + processStyles(doc); + } + + // Parse placemarks + if (!!doc.reload && !!doc.markers) { + for (i = 0; i < doc.markers.length; i++) { + doc.markers[i].active = false; + } + } + var placemark, node, coords, path, marker, poly; + var placemark, coords, path, pathLength, marker, polygonNodes, coordList; + var placemarkNodes = responseXML.getElementsByTagName('Placemark'); + for (pm = 0; pm < placemarkNodes.length; pm++) { + // Init the placemark object + node = placemarkNodes[pm]; + placemark = { + name: geoXML3.nodeValue(node.getElementsByTagName('name')[0]), + description: geoXML3.nodeValue(node.getElementsByTagName('description')[0]), + styleUrl: geoXML3.nodeValue(node.getElementsByTagName('styleUrl')[0]) + }; + var defaultStyle = { + color: "ff000000", // black + width: 1, + fill: true, + outline: true, + fillcolor: "3fff0000" // blue + }; + placemark.style = doc.styles[placemark.styleUrl] || defaultStyle; + // inline style overrides shared style + var inlineStyles = node.getElementsByTagName('Style'); + if (inlineStyles && (inlineStyles.length > 0)) { + var style = processStyle(node,doc.styles,"inline"); + processStyleID(style); + if (style) placemark.style = style; + } + if (/^https?:\/\//.test(placemark.description)) { + placemark.description = ['<a href="', placemark.description, '">', placemark.description, '</a>'].join(''); + } + + // process MultiGeometry + var GeometryNodes = node.getElementsByTagName('coordinates'); + var Geometry = null; + if (!!GeometryNodes && (GeometryNodes.length > 0)) { + for (var gn=0;gn<GeometryNodes.length;gn++) { + if (!GeometryNodes[gn].parentNode || + !GeometryNodes[gn].parentNode.nodeName) { + + } else { // parentNode.nodeName exists + var GeometryPN = GeometryNodes[gn].parentNode; + Geometry = GeometryPN.nodeName; + + // Extract the coordinates + // What sort of placemark? + switch(Geometry) { + case "Point": + placemark.Point = processPlacemarkCoords(node, "Point")[0]; + placemark.latlng = new google.maps.LatLng(placemark.Point.coordinates[0].lat, placemark.Point.coordinates[0].lng); + pathLength = 1; + break; + case "LinearRing": + // Polygon/line + polygonNodes = node.getElementsByTagName('Polygon'); + // Polygon + if (!placemark.Polygon) + placemark.Polygon = [{ + outerBoundaryIs: {coordinates: []}, + innerBoundaryIs: [{coordinates: []}] + }]; + for (var pg=0;pg<polygonNodes.length;pg++) { + placemark.Polygon[pg] = { + outerBoundaryIs: {coordinates: []}, + innerBoundaryIs: [{coordinates: []}] + } + placemark.Polygon[pg].outerBoundaryIs = processPlacemarkCoords(polygonNodes[pg], "outerBoundaryIs"); + placemark.Polygon[pg].innerBoundaryIs = processPlacemarkCoords(polygonNodes[pg], "innerBoundaryIs"); + } + coordList = placemark.Polygon[0].outerBoundaryIs; + break; + + case "LineString": + pathLength = 0; + placemark.LineString = processPlacemarkCoords(node,"LineString"); + break; + + default: + break; + } + } // parentNode.nodeName exists + } // GeometryNodes loop + } // if GeometryNodes + // call the custom placemark parse function if it is defined + if (!!parserOptions.pmParseFn) parserOptions.pmParseFn(node, placemark); + doc.placemarks.push(placemark); + + if (placemark.Point) { + if (parserOptions.zoom && !!google.maps) { + doc.bounds = doc.bounds || new google.maps.LatLngBounds(); + doc.bounds.extend(placemark.latlng); + } + + if (!!parserOptions.createMarker) { + // User-defined marker handler + parserOptions.createMarker(placemark, doc); + } else { // !user defined createMarker + // Check to see if this marker was created on a previous load of this document + var found = false; + if (!!doc) { + doc.markers = doc.markers || []; + if (doc.reload) { + for (var j = 0; j < doc.markers.length; j++) { + if (doc.markers[j].getPosition().equals(placemark.latlng)) { + found = doc.markers[j].active = true; + break; + } + } + } + } + + if (!found) { + // Call the built-in marker creator + marker = createMarker(placemark, doc); + marker.active = true; + } + } + } + if (placemark.Polygon) { // poly test 2 + if (!!doc) { + doc.gpolygons = doc.gpolygons || []; + } + + if (!!parserOptions.createPolygon) { + // User-defined polygon handler + poly = parserOptions.createPolygon(placemark, doc); + } else { // ! user defined createPolygon + // Check to see if this marker was created on a previous load of this document + poly = createPolygon(placemark,doc); + poly.active = true; + } + if (parserOptions.zoom && !!google.maps) { + doc.bounds = doc.bounds || new google.maps.LatLngBounds(); + doc.bounds.union(poly.bounds); + } + } + if (placemark.LineString) { // polyline + if (!!doc) { + doc.gpolylines = doc.gpolylines || []; + } + if (!!parserOptions.createPolyline) { + // User-defined polyline handler + poly = parserOptions.createPolyline(placemark, doc); + } else { // ! user defined createPolyline + // Check to see if this marker was created on a previous load of this document + poly = createPolyline(placemark,doc); + poly.active = true; + } + if (parserOptions.zoom && !!google.maps) { + doc.bounds = doc.bounds || new google.maps.LatLngBounds(); + doc.bounds.union(poly.bounds); + } + } + + } // placemark loop + + if (!!doc.reload && !!doc.markers) { + for (i = doc.markers.length - 1; i >= 0 ; i--) { + if (!doc.markers[i].active) { + if (!!doc.markers[i].infoWindow) { + doc.markers[i].infoWindow.close(); + } + doc.markers[i].setMap(null); + doc.markers.splice(i, 1); + } + } + } + + // Parse ground overlays + if (!!doc.reload && !!doc.groundoverlays) { + for (i = 0; i < doc.groundoverlays.length; i++) { + doc.groundoverlays[i].active = false; + } + } + + if (!!doc) { + doc.groundoverlays = doc.groundoverlays || []; + } + // doc.groundoverlays =[]; + var groundOverlay, color, transparency, overlay; + var groundNodes = responseXML.getElementsByTagName('GroundOverlay'); + for (i = 0; i < groundNodes.length; i++) { + node = groundNodes[i]; + + // Init the ground overlay object + groundOverlay = { + name: geoXML3.nodeValue(node.getElementsByTagName('name')[0]), + description: geoXML3.nodeValue(node.getElementsByTagName('description')[0]), + icon: {href: geoXML3.nodeValue(node.getElementsByTagName('href')[0])}, + latLonBox: { + north: parseFloat(geoXML3.nodeValue(node.getElementsByTagName('north')[0])), + east: parseFloat(geoXML3.nodeValue(node.getElementsByTagName('east')[0])), + south: parseFloat(geoXML3.nodeValue(node.getElementsByTagName('south')[0])), + west: parseFloat(geoXML3.nodeValue(node.getElementsByTagName('west')[0])) + } + }; + if (parserOptions.zoom && !!google.maps) { + doc.bounds = doc.bounds || new google.maps.LatLngBounds(); + doc.bounds.union(new google.maps.LatLngBounds( + new google.maps.LatLng(groundOverlay.latLonBox.south, groundOverlay.latLonBox.west), + new google.maps.LatLng(groundOverlay.latLonBox.north, groundOverlay.latLonBox.east) + )); + } + + // Opacity is encoded in the color node + var colorNode = node.getElementsByTagName('color'); + if ( colorNode && colorNode.length && (colorNode.length > 0)) { + groundOverlay.opacity = geoXML3.getOpacity(nodeValue(colorNode[0])); + } else { + groundOverlay.opacity = 0.45; + } + + doc.groundoverlays.push(groundOverlay); + + if (!!parserOptions.createOverlay) { + // User-defined overlay handler + parserOptions.createOverlay(groundOverlay, doc); + } else { // ! user defined createOverlay + // Check to see if this overlay was created on a previous load of this document + var found = false; + if (!!doc) { + doc.groundoverlays = doc.groundoverlays || []; + if (doc.reload) { + overlayBounds = new google.maps.LatLngBounds( + new google.maps.LatLng(groundOverlay.latLonBox.south, groundOverlay.latLonBox.west), + new google.maps.LatLng(groundOverlay.latLonBox.north, groundOverlay.latLonBox.east)); + var overlays = doc.groundoverlays; + for (i = overlays.length; i--;) { + if ((overlays[i].bounds().equals(overlayBounds)) && + (overlays.url_ === groundOverlay.icon.href)) { + found = overlays[i].active = true; + break; + } + } + } + } + + if (!found) { + // Call the built-in overlay creator + overlay = createOverlay(groundOverlay, doc); + overlay.active = true; + } + } + if (!!doc.reload && !!doc.groundoverlays && !!doc.groundoverlays.length) { + var overlays = doc.groundoverlays; + for (i = overlays.length; i--;) { + if (!overlays[i].active) { + overlays[i].remove(); + overlays.splice(i, 1); + } + } + doc.groundoverlays = overlays; + } + } + // Parse network links + var networkLink; + var docPath = document.location.pathname.split('/'); + docPath = docPath.splice(0, docPath.length - 1).join('/'); + var linkNodes = responseXML.getElementsByTagName('NetworkLink'); + for (i = 0; i < linkNodes.length; i++) { + node = linkNodes[i]; + + // Init the network link object + networkLink = { + name: geoXML3.nodeValue(node.getElementsByTagName('name')[0]), + link: { + href: geoXML3.nodeValue(node.getElementsByTagName('href')[0]), + refreshMode: geoXML3.nodeValue(node.getElementsByTagName('refreshMode')[0]) + } + }; + + // Establish the specific refresh mode + if (networkLink.link.refreshMode === '') { + networkLink.link.refreshMode = 'onChange'; + } + if (networkLink.link.refreshMode === 'onInterval') { + networkLink.link.refreshInterval = parseFloat(geoXML3.nodeValue(node.getElementsByTagName('refreshInterval')[0])); + if (isNaN(networkLink.link.refreshInterval)) { + networkLink.link.refreshInterval = 0; + } + } else if (networkLink.link.refreshMode === 'onChange') { + networkLink.link.viewRefreshMode = geoXML3.nodeValue(node.getElementsByTagName('viewRefreshMode')[0]); + if (networkLink.link.viewRefreshMode === '') { + networkLink.link.viewRefreshMode = 'never'; + } + if (networkLink.link.viewRefreshMode === 'onStop') { + networkLink.link.viewRefreshTime = geoXML3.nodeValue(node.getElementsByTagName('refreshMode')[0]); + networkLink.link.viewFormat = geoXML3.nodeValue(node.getElementsByTagName('refreshMode')[0]); + if (networkLink.link.viewFormat === '') { + networkLink.link.viewFormat = 'BBOX=[bboxWest],[bboxSouth],[bboxEast],[bboxNorth]'; + } + } + } + + if (!/^[\/|http]/.test(networkLink.link.href)) { + // Fully-qualify the HREF + networkLink.link.href = docPath + '/' + networkLink.link.href; + } + + // Apply the link + if ((networkLink.link.refreshMode === 'onInterval') && + (networkLink.link.refreshInterval > 0)) { + // Reload at regular intervals + setInterval(parserName + '.parse("' + networkLink.link.href + '")', + 1000 * networkLink.link.refreshInterval); + } else if (networkLink.link.refreshMode === 'onChange') { + if (networkLink.link.viewRefreshMode === 'never') { + // Load the link just once + doc.internals.parser.parse(networkLink.link.href, doc.internals.docSet); + } else if (networkLink.link.viewRefreshMode === 'onStop') { + // Reload when the map view changes + + } + } + } +} + + if (!!doc.bounds) { + doc.internals.bounds = doc.internals.bounds || new google.maps.LatLngBounds(); + doc.internals.bounds.union(doc.bounds); + } + if (!!doc.markers || !!doc.groundoverlays || !!doc.gpolylines || !!doc.gpolygons) { + doc.internals.parseOnly = false; + } + + doc.internals.remaining -= 1; + if (doc.internals.remaining === 0) { + // We're done processing this set of KML documents + // Options that get invoked after parsing completes + if (!!doc.internals.bounds) { + parserOptions.map.fitBounds(doc.internals.bounds); + } + if (parserOptions.afterParse) { + parserOptions.afterParse(doc.internals.docSet); + } + + if (!doc.internals.parseOnly) { + // geoXML3 is not being used only as a real-time parser, so keep the processed documents around + for (var i=(doc.internals.docSet.length-1);i>=0;i--) { + docs.push(doc.internals.docSet[i]); + } + } + } + }; + +var kmlColor = function (kmlIn) { + var kmlColor = {}; + if (kmlIn) { + aa = kmlIn.substr(0,2); + bb = kmlIn.substr(2,2); + gg = kmlIn.substr(4,2); + rr = kmlIn.substr(6,2); + kmlColor.color = "#" + rr + gg + bb; + kmlColor.opacity = parseInt(aa,16)/256; + } else { + // defaults + kmlColor.color = randomColor(); + kmlColor.opacity = 0.45; + } + return kmlColor; +} + +var randomColor = function(){ + var color="#"; + var colorNum = Math.random()*8388607.0; // 8388607 = Math.pow(2,23)-1 + var colorStr = colorNum.toString(16); + color += colorStr.substring(0,colorStr.indexOf('.')); + return color; +}; + + var processStyleID = function (style) { + var zeroPoint = new google.maps.Point(0,0); + if (!!style.href) { + var markerRegEx = /\/(red|blue|green|yellow|lightblue|purple|pink|orange|pause|go|stop)(-dot)?\.png/; + if (markerRegEx.test(style.href)) { + //bottom middle + var anchorPoint = new google.maps.Point(16*style.scale, 32*style.scale); + } else { + var anchorPoint = new google.maps.Point(16*style.scale, 12*style.scale); + } + // Init the style object with a standard KML icon + style.icon = new google.maps.MarkerImage( + style.href, + new google.maps.Size(32*style.scale, 32*style.scale), + zeroPoint, + // bottom middle + anchorPoint, + new google.maps.Size(32,32) + + ); + + // Look for a predictable shadow + var stdRegEx = /\/(red|blue|green|yellow|lightblue|purple|pink|orange)(-dot)?\.png/; + var shadowSize = new google.maps.Size(59, 32); + var shadowPoint = new google.maps.Point(16,32); + if (stdRegEx.test(style.href)) { + // A standard GMap-style marker icon + style.shadow = new google.maps.MarkerImage( + 'http://maps.google.com/mapfiles/ms/micons/msmarker.shadow.png', + shadowSize, + zeroPoint, + shadowPoint); + } else if (style.href.indexOf('-pushpin.png') > -1) { + // Pushpin marker icon + style.shadow = new google.maps.MarkerImage( + 'http://maps.google.com/mapfiles/ms/micons/pushpin_shadow.png', + shadowSize, + zeroPoint, + shadowPoint); + } else { + // Other MyMaps KML standard icon + style.shadow = new google.maps.MarkerImage( + style.href.replace('.png', '.shadow.png'), + shadowSize, + zeroPoint, + shadowPoint); + } + } + } + + var processStyles = function (doc) { + for (var styleID in doc.styles) { + processStyleID(doc.styles[styleID]); + } + }; + + var createMarker = function (placemark, doc) { + // create a Marker to the map from a placemark KML object + + // Load basic marker properties + var markerOptions = geoXML3.combineOptions(parserOptions.markerOptions, { + map: parserOptions.map, + position: new google.maps.LatLng(placemark.Point.coordinates[0].lat, placemark.Point.coordinates[0].lng), + title: placemark.name, + zIndex: Math.round(placemark.Point.coordinates[0].lat * -100000)<<5, + icon: placemark.style.icon, + shadow: placemark.style.shadow + }); + + // Create the marker on the map + var marker = new google.maps.Marker(markerOptions); + if (!!doc) { + doc.markers.push(marker); + } + + // Set up and create the infowindow + var infoWindowOptions = geoXML3.combineOptions(parserOptions.infoWindowOptions, { + content: '<div class="geoxml3_infowindow"><h3>' + placemark.name + + '</h3><div>' + placemark.description + '</div></div>', + pixelOffset: new google.maps.Size(0, 2) + }); + if (parserOptions.infoWindow) { + marker.infoWindow = parserOptions.infoWindow; + } else { + marker.infoWindow = new google.maps.InfoWindow(infoWindowOptions); + } + // Infowindow-opening event handler + google.maps.event.addListener(marker, 'click', function() { + marker.infoWindow.setOptions(infoWindowOptions); + this.infoWindow.open(this.map, this); + }); + placemark.marker = marker; + return marker; + }; + + var createOverlay = function (groundOverlay, doc) { + // Add a ProjectedOverlay to the map from a groundOverlay KML object + + if (!window.ProjectedOverlay) { + throw 'geoXML3 error: ProjectedOverlay not found while rendering GroundOverlay from KML'; + } + + var bounds = new google.maps.LatLngBounds( + new google.maps.LatLng(groundOverlay.latLonBox.south, groundOverlay.latLonBox.west), + new google.maps.LatLng(groundOverlay.latLonBox.north, groundOverlay.latLonBox.east) + ); + var overlayOptions = geoXML3.combineOptions(parserOptions.overlayOptions, {percentOpacity: groundOverlay.opacity*100}); + var overlay = new ProjectedOverlay(parserOptions.map, groundOverlay.icon.href, bounds, overlayOptions); + + if (!!doc) { + doc.ggroundoverlays = doc.ggroundoverlays || []; + doc.ggroundoverlays.push(overlay); + } + + return overlay; + }; + +// Create Polyline + + var createPolyline = function(placemark, doc) { + var path = []; + for (var j=0; j<placemark.LineString.length; j++) { + var coords = placemark.LineString[j].coordinates; + var bounds = new google.maps.LatLngBounds(); + for (var i=0;i<coords.length;i++) { + var pt = new google.maps.LatLng(coords[i].lat, coords[i].lng); + path.push(pt); + bounds.extend(pt); + } + } + // point to open the infowindow if triggered + var point = path[Math.floor(path.length/2)]; + // Load basic polyline properties + var kmlStrokeColor = kmlColor(placemark.style.color); + var polyOptions = geoXML3.combineOptions(parserOptions.polylineOptions, { + map: parserOptions.map, + path: path, + strokeColor: kmlStrokeColor.color, + strokeWeight: placemark.style.width, + strokeOpacity: kmlStrokeColor.opacity, + title: placemark.name + }); + var infoWindowOptions = geoXML3.combineOptions(parserOptions.infoWindowOptions, { + content: '<div class="geoxml3_infowindow"><h3>' + placemark.name + + '</h3><div>' + placemark.description + '</div></div>', + pixelOffset: new google.maps.Size(0, 2) + }); + var p = new google.maps.Polyline(polyOptions); + p.bounds = bounds; + if (parserOptions.infoWindow) { + p.infoWindow = parserOptions.infoWindow; + } else { + p.infoWindow = new google.maps.InfoWindow(infoWindowOptions); + } + // Infowindow-opening event handler + google.maps.event.addListener(p, 'click', function(e) { + p.infoWindow.setOptions(infoWindowOptions); + if (e && e.latLng) { + p.infoWindow.setPosition(e.latLng); + } else { + p.infoWindow.setPosition(point); + } + p.infoWindow.open(this.map); + }); + if (!!doc) doc.gpolylines.push(p); + placemark.polyline = p; + return p; +} + +// Create Polygon + +var createPolygon = function(placemark, doc) { + var bounds = new google.maps.LatLngBounds(); + var pathsLength = 0; + var paths = []; + for (var polygonPart=0;polygonPart<placemark.Polygon.length;polygonPart++) { + for (var j=0; j<placemark.Polygon[polygonPart].outerBoundaryIs.length; j++) { + var coords = placemark.Polygon[polygonPart].outerBoundaryIs[j].coordinates; + var path = []; + for (var i=0;i<coords.length;i++) { + var pt = new google.maps.LatLng(coords[i].lat, coords[i].lng); + path.push(pt); + bounds.extend(pt); + } + paths.push(path); + pathsLength += path.length; + } + for (var j=0; j<placemark.Polygon[polygonPart].innerBoundaryIs.length; j++) { + var coords = placemark.Polygon[polygonPart].innerBoundaryIs[j].coordinates; + var path = []; + for (var i=0;i<coords.length;i++) { + var pt = new google.maps.LatLng(coords[i].lat, coords[i].lng); + path.push(pt); + bounds.extend(pt); + } + paths.push(path); + pathsLength += path.length; + } + } + + // Load basic polygon properties + var kmlStrokeColor = kmlColor(placemark.style.color); + var kmlFillColor = kmlColor(placemark.style.fillcolor); + if (!placemark.style.fill) kmlFillColor.opacity = 0.0; + var strokeWeight = placemark.style.width; + if (!placemark.style.outline) { + strokeWeight = 0; + kmlStrokeColor.opacity = 0.0; + } + var polyOptions = geoXML3.combineOptions(parserOptions.polygonOptions, { + map: parserOptions.map, + paths: paths, + title: placemark.name, + strokeColor: kmlStrokeColor.color, + strokeWeight: strokeWeight, + strokeOpacity: kmlStrokeColor.opacity, + fillColor: kmlFillColor.color, + fillOpacity: kmlFillColor.opacity + }); + + var infoWindowOptions = geoXML3.combineOptions(parserOptions.infoWindowOptions, { + content: '<div class="geoxml3_infowindow"><h3>' + placemark.name + + '</h3><div>' + placemark.description + '</div></div>', + pixelOffset: new google.maps.Size(0, 2) + }); + var p = new google.maps.Polygon(polyOptions); + p.bounds = bounds; + if (parserOptions.infoWindow) { + p.infoWindow = parserOptions.infoWindow; + } else { + p.infoWindow = new google.maps.InfoWindow(infoWindowOptions); + } + // Infowindow-opening event handler + google.maps.event.addListener(p, 'click', function(e) { + p.infoWindow.setOptions(infoWindowOptions); + if (e && e.latLng) { + p.infoWindow.setPosition(e.latLng); + } else { + p.infoWindow.setPosition(p.bounds.getCenter()); + } + p.infoWindow.open(this.map); + }); + if (!!doc) doc.gpolygons.push(p); + placemark.polygon = p; + return p; +} + + return { + // Expose some properties and methods + + options: parserOptions, + docs: docs, + + parse: parse, + hideDocument: hideDocument, + showDocument: showDocument, + processStyles: processStyles, + createMarker: createMarker, + createOverlay: createOverlay, + createPolyline: createPolyline, + createPolygon: createPolygon + }; +}; +// End of KML Parser + +// Helper objects and functions +geoXML3.getOpacity = function (kmlColor) { + // Extract opacity encoded in a KML color value. Returns a number between 0 and 1. + if (!!kmlColor && + (kmlColor !== '') && + (kmlColor.length == 8)) { + var transparency = parseInt(kmlColor.substr(0, 2), 16); + return transparency / 255; + } else { + return 1; + } +}; + +// Log a message to the debugging console, if one exists +geoXML3.log = function(msg) { + if (!!window.console) { + console.log(msg); + } else { alert("log:"+msg); } +}; + +// Combine two options objects: a set of default values and a set of override values +geoXML3.combineOptions = function (overrides, defaults) { + var result = {}; + if (!!overrides) { + for (var prop in overrides) { + if (overrides.hasOwnProperty(prop)) { + result[prop] = overrides[prop]; + } + } + } + if (!!defaults) { + for (prop in defaults) { + if (defaults.hasOwnProperty(prop) && (result[prop] === undefined)) { + result[prop] = defaults[prop]; + } + } + } + return result; +}; + +// Retrieve an XML document from url and pass it to callback as a DOM document +geoXML3.fetchers = []; + +// parse text to XML doc +/** + * Parses the given XML string and returns the parsed document in a + * DOM data structure. This function will return an empty DOM node if + * XML parsing is not supported in this browser. + * @param {string} str XML string. + * @return {Element|Document} DOM. + */ +geoXML3.xmlParse = function (str) { + if (typeof ActiveXObject != 'undefined' && typeof GetObject != 'undefined') { + var doc = new ActiveXObject('Microsoft.XMLDOM'); + doc.loadXML(str); + return doc; + } + + if (typeof DOMParser != 'undefined') { + return (new DOMParser()).parseFromString(str, 'text/xml'); + } + + return createElement('div', null); +} + +geoXML3.fetchXML = function (url, callback) { + function timeoutHandler() { + callback(); + }; + + var xhrFetcher; + if (!!geoXML3.fetchers.length) { + xhrFetcher = geoXML3.fetchers.pop(); + } else { + if (!!window.XMLHttpRequest) { + xhrFetcher = new window.XMLHttpRequest(); // Most browsers + } else if (!!window.ActiveXObject) { + xhrFetcher = new window.ActiveXObject('Microsoft.XMLHTTP'); // Some IE + } + } + + if (!xhrFetcher) { + geoXML3.log('Unable to create XHR object'); + callback(null); + } else { + xhrFetcher.open('GET', url, true); + xhrFetcher.onreadystatechange = function () { + if (xhrFetcher.readyState === 4) { + // Retrieval complete + if (!!geoXML3.xhrtimeout) + clearTimeout(geoXML3.xhrtimeout); + if (xhrFetcher.status >= 400) { + geoXML3.log('HTTP error ' + xhrFetcher.status + ' retrieving ' + url); + callback(); + } else { + // Returned successfully + callback(geoXML3.xmlParse(xhrFetcher.responseText)); + } + // We're done with this fetcher object + geoXML3.fetchers.push(xhrFetcher); + } + }; + geoXML3.xhrtimeout = setTimeout(timeoutHandler, 60000); + xhrFetcher.send(null); + } +}; + +//nodeValue: Extract the text value of a DOM node, with leading and trailing whitespace trimmed +geoXML3.nodeValue = function(node) { + var retStr=""; + if (!node) { + return ''; + } + if(node.nodeType==3||node.nodeType==4||node.nodeType==2){ + retStr+=node.nodeValue; + }else if(node.nodeType==1||node.nodeType==9||node.nodeType==11){ + for(var i=0;i<node.childNodes.length;++i){ + retStr+=arguments.callee(node.childNodes[i]); + } + } + return retStr; +};
\ No newline at end of file diff --git a/protected/extensions/egmap/assets/infobox_packed.js b/protected/extensions/egmap/assets/infobox_packed.js new file mode 100644 index 0000000..d621e26 --- /dev/null +++ b/protected/extensions/egmap/assets/infobox_packed.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('7 p(a){a=a||{};5.8.1N.2h(2,32);2.L=a.1u||"";2.1D=a.1q||H;2.P=a.1H||0;2.E=a.1B||1f 5.8.1U(0,0);2.B=a.W||1f 5.8.2t(0,0);2.S=a.11||q;2.1n=a.1l||"28";2.1k=a.D||{};2.1G=a.1E||"34";2.M=a.19||"2W://2Q.5.2L/2I/2G/2F/1v.2z";3(a.19===""){2.M=""}2.1i=a.1r||1f 5.8.1U(1,1);2.Y=a.1s||H;2.1a=a.1p||H;2.1K=a.2k||"2g";2.17=a.1m||H;2.4=q;2.w=q;2.X=q;2.16=q;2.15=q;2.13=q;2.12=q;2.O=q}p.r=1f 5.8.1N();p.r.22=7(){6 a;6 d=2;6 c=7(e){e.1Z=U;3(e.18){e.18()}};6 b=7(e){e.2S=H;3(e.1Y){e.1Y()}3(!d.17){c(e)}};3(!2.4){2.4=1g.2K("2J");2.1d();3(t 2.L.1w==="u"){2.4.J=2.F()+2.L}v{2.4.J=2.F();2.4.1b(2.L)}2.2y()[2.1K].1b(2.4);2.1F();3(2.4.9.A){2.O=U}v{3(2.P!==0&&2.4.Z>2.P){2.4.9.A=2.P;2.4.9.2u="2s";2.O=U}v{a=2.24();2.4.9.A=(2.4.Z-a.14-a.T)+"R";2.O=H}}2.1t(2.1D);3(!2.17){2.X=5.8.s.I(2.4,"2n",c);2.16=5.8.s.I(2.4,"1L",c);2.15=5.8.s.I(2.4,"2m",c);2.1o=5.8.s.I(2.4,"2l",7(e){2.9.1J="2j"})}2.12=5.8.s.I(2.4,"2i",b);5.8.s.Q(2,"2f")}};p.r.F=7(){6 a="";3(2.M!==""){a="<2e";a+=" 2d=\'"+2.M+"\'";a+=" 2c=T";a+=" 9=\'";a+=" W: 2b;";a+=" 1J: 2a;";a+=" 29: "+2.1G+";";a+="\'>"}N a};p.r.1F=7(){6 a;3(2.M!==""){a=2.4.27;2.w=5.8.s.I(a,\'1L\',2.1I())}v{2.w=q}};p.r.1I=7(){6 a=2;N 7(e){e.1Z=U;3(e.18){e.18()}a.1v();5.8.s.Q(a,"26")}};p.r.1t=7(d){6 m;6 n;6 e=0,G=0;3(!d){m=2.25();3(m 39 5.8.38){3(!m.23().37(2.B)){m.36(2.B)}n=m.23();6 a=m.35();6 h=a.Z;6 f=a.21;6 k=2.E.A;6 l=2.E.1j;6 g=2.4.Z;6 b=2.4.21;6 i=2.1i.A;6 j=2.1i.1j;6 o=2.20().31(2.B);3(o.x<(-k+i)){e=o.x+k-i}v 3((o.x+g+k+i)>h){e=o.x+g+k+i-h}3(2.1a){3(o.y<(-l+j+b)){G=o.y+l-j-b}v 3((o.y+l+j)>f){G=o.y+l+j-f}}v{3(o.y<(-l+j)){G=o.y+l-j}v 3((o.y+b+l+j)>f){G=o.y+b+l+j-f}}3(!(e===0&&G===0)){6 c=m.30();m.2Z(e,G)}}}};p.r.1d=7(){6 i,D;3(2.4){2.4.2Y=2.1n;2.4.9.2X="";D=2.1k;2V(i 2U D){3(D.2R(i)){2.4.9[i]=D[i]}}3(t 2.4.9.1h!=="u"&&2.4.9.1h!==""){2.4.9.2P="2O(1h="+(2.4.9.1h*2N)+")"}2.4.9.W="2M";2.4.9.V=\'1y\';3(2.S!==q){2.4.9.11=2.S}}};p.r.24=7(){6 c;6 a={1e:0,1c:0,14:0,T:0};6 b=2.4;3(1g.1x&&1g.1x.1V){c=b.2H.1x.1V(b,"");3(c){a.1e=C(c.1T,10)||0;a.1c=C(c.1S,10)||0;a.14=C(c.1R,10)||0;a.T=C(c.1W,10)||0}}v 3(1g.2E.K){3(b.K){a.1e=C(b.K.1T,10)||0;a.1c=C(b.K.1S,10)||0;a.14=C(b.K.1R,10)||0;a.T=C(b.K.1W,10)||0}}N a};p.r.2D=7(){3(2.4){2.4.2C.2B(2.4);2.4=q}};p.r.1A=7(){2.22();6 a=2.20().2A(2.B);2.4.9.14=(a.x+2.E.A)+"R";3(2.1a){2.4.9.1c=-(a.y+2.E.1j)+"R"}v{2.4.9.1e=(a.y+2.E.1j)+"R"}3(2.Y){2.4.9.V=\'1y\'}v{2.4.9.V="1X"}};p.r.2T=7(a){3(t a.1l!=="u"){2.1n=a.1l;2.1d()}3(t a.D!=="u"){2.1k=a.D;2.1d()}3(t a.1u!=="u"){2.1Q(a.1u)}3(t a.1q!=="u"){2.1D=a.1q}3(t a.1H!=="u"){2.P=a.1H}3(t a.1B!=="u"){2.E=a.1B}3(t a.1p!=="u"){2.1a=a.1p}3(t a.W!=="u"){2.1z(a.W)}3(t a.11!=="u"){2.1P(a.11)}3(t a.1E!=="u"){2.1G=a.1E}3(t a.19!=="u"){2.M=a.19}3(t a.1r!=="u"){2.1i=a.1r}3(t a.1s!=="u"){2.Y=a.1s}3(t a.1m!=="u"){2.17=a.1m}3(2.4){2.1A()}};p.r.1Q=7(a){2.L=a;3(2.4){3(2.w){5.8.s.z(2.w);2.w=q}3(!2.O){2.4.9.A=""}3(t a.1w==="u"){2.4.J=2.F()+a}v{2.4.J=2.F();2.4.1b(a)}3(!2.O){2.4.9.A=2.4.Z+"R";3(t a.1w==="u"){2.4.J=2.F()+a}v{2.4.J=2.F();2.4.1b(a)}}2.1F()}5.8.s.Q(2,"2x")};p.r.1z=7(a){2.B=a;3(2.4){2.1A()}5.8.s.Q(2,"1O")};p.r.1P=7(a){2.S=a;3(2.4){2.4.9.11=a}5.8.s.Q(2,"2w")};p.r.2v=7(){N 2.L};p.r.1C=7(){N 2.B};p.r.33=7(){N 2.S};p.r.2r=7(){2.Y=H;3(2.4){2.4.9.V="1X"}};p.r.2q=7(){2.Y=U;3(2.4){2.4.9.V="1y"}};p.r.2p=7(c,b){6 a=2;3(b){2.B=b.1C();2.13=5.8.s.2o(b,"1O",7(){a.1z(2.1C())})}2.1M(c);3(2.4){2.1t()}};p.r.1v=7(){3(2.w){5.8.s.z(2.w);2.w=q}3(2.X){5.8.s.z(2.X);5.8.s.z(2.16);5.8.s.z(2.15);5.8.s.z(2.1o);2.X=q;2.16=q;2.15=q;2.1o=q}3(2.13){5.8.s.z(2.13);2.13=q}3(2.12){5.8.s.z(2.12);2.12=q}2.1M(q)};',62,196,'||this|if|div_|google|var|function|maps|style||||||||||||||||InfoBox|null|prototype|event|typeof|undefined|else|closeListener_|||removeListener|width|position_|parseInt|boxStyle|pixelOffset_|getCloseBoxImg_|yOffset|false|addDomListener|innerHTML|currentStyle|content_|closeBoxURL_|return|fixedWidthSet_|maxWidth_|trigger|px|zIndex_|right|true|visibility|position|eventListener1_|isHidden_|offsetWidth||zIndex|contextListener_|moveListener_|left|eventListener3_|eventListener2_|enableEventPropagation_|stopPropagation|closeBoxURL|alignBottom_|appendChild|bottom|setBoxStyle_|top|new|document|opacity|infoBoxClearance_|height|boxStyle_|boxClass|enableEventPropagation|boxClass_|eventListener4_|alignBottom|disableAutoPan|infoBoxClearance|isHidden|panBox_|content|close|nodeType|defaultView|hidden|setPosition|draw|pixelOffset|getPosition|disableAutoPan_|closeBoxMargin|addClickHandler_|closeBoxMargin_|maxWidth|getCloseClickHandler_|cursor|pane_|click|setMap|OverlayView|position_changed|setZIndex|setContent|borderLeftWidth|borderBottomWidth|borderTopWidth|Size|getComputedStyle|borderRightWidth|visible|preventDefault|cancelBubble|getProjection|offsetHeight|createInfoBoxDiv_|getBounds|getBoxWidths_|getMap|closeclick|firstChild|infoBox|margin|pointer|relative|align|src|img|domready|floatPane|apply|contextmenu|default|pane|mouseover|dblclick|mousedown|addListener|open|hide|show|auto|LatLng|overflow|getContent|zindex_changed|content_changed|getPanes|gif|fromLatLngToDivPixel|removeChild|parentNode|onRemove|documentElement|mapfiles|en_us|ownerDocument|intl|div|createElement|com|absolute|100|alpha|filter|www|hasOwnProperty|returnValue|setOptions|in|for|http|cssText|className|panBy|getCenter|fromLatLngToContainerPixel|arguments|getZIndex|2px|getDiv|setCenter|contains|Map|instanceof'.split('|'),0,{}))
\ No newline at end of file diff --git a/protected/extensions/egmap/assets/keydragzoom_packed.js b/protected/extensions/egmap/assets/keydragzoom_packed.js new file mode 100644 index 0000000..e5c184c --- /dev/null +++ b/protected/extensions/egmap/assets/keydragzoom_packed.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(B(){9 u=B(a){9 b;2t(a){1t"4h":b="3V";1w;1t"3z":b="2r";1w;1t"3f":b="37";1w;2Y:b=a}N b};9 t=B(h){9 b;9 a={};A(H.1F&&H.1F.1A){b=h.3s.1F.1A(h,"");A(b){a.F=O(b.2o,10)||0;a.1m=O(b.2h,10)||0;a.C=O(b.2Q,10)||0;a.1n=O(b.2M,10)||0;N a}}1f A(H.1x.1y){A(h.1y){a.F=O(u(h.1y.2o),10)||0;a.1m=O(u(h.1y.2h),10)||0;a.C=O(u(h.1y.2Q),10)||0;a.1n=O(u(h.1y.2M),10)||0;N a}}a.F=O(h.7["1I-F-G"],10)||0;a.1m=O(h.7["1I-1m-G"],10)||0;a.C=O(h.7["1I-C-G"],10)||0;a.1n=O(h.7["1I-1n-G"],10)||0;N a};9 v={x:0,y:0};9 s=B(e){v.x=(1i H.1x.1P!=="1r"?H.1x.1P:H.24.1P);v.y=(1i H.1x.1N!=="1r"?H.1x.1N:H.24.1N)};s();9 q=B(e){9 a=0,1L=0;e=e||1R.J;A(1i e.2n!=="1r"){a=e.2n;1L=e.36}1f A(1i e.2F!=="1r"){a=e.2F+v.x;1L=e.31+v.y}N{C:a,F:1L}};9 n=B(h){9 e=h.2k;9 g=h.2g;9 b=h.2K;4f(b!==S){A(b!==H.24&&b!==H.1x){e-=b.1P;g-=b.1N}9 m=b;9 f=m.2k;9 a=m.2g;A(!f&&!a&&1R.1A){9 d=H.1F.1A(m,S).40||H.1F.1A(m,S).3Z;A(d){A(1i d==="3X"){9 c=d.3S(",");f+=O(c[4],10)||0;a+=O(c[5],10)||0}}}e+=f;g+=a;b=b.2K}N{C:e,F:g}};9 o=B(a,b){A(a&&b){1b(9 x 3L b){A(b.3J(x)){a[x]=b[x]}}}N a};9 r=B(h,a){A(1i a!=="1r"){h.7.1u=a}A(1i h.7.1u!=="1r"&&h.7.1u!==""){h.7.3I="3E(1u="+(h.7.1u*3C)+")"}};B R(a,d){9 b=6;9 c=15 E.D.3w();c.3u=B(){b.2v(a,d)};c.3q=B(){};c.3p=B(){};c.2u(a);6.1C=c}R.P.2v=B(a,c){9 i;9 b=6;6.L=a;c=c||{};6.14=c.3j||"1M";6.14=6.14.3h();6.T=t(6.L.13());6.8=[];1b(i=0;i<4;i++){6.8[i]=H.1O("22");6.8[i].3a=B(){N X};o(6.8[i].7,{27:"34",1u:0.25,2A:"32"});o(6.8[i].7,c.30);o(6.8[i].7,c.2Z);o(6.8[i].7,{1K:"21",2j:"2i",W:"1c"});A(6.14==="1M"){6.8[i].7.2W="1c"}r(6.8[i]);A(6.8[i].7.27==="2V"){6.8[i].7.27="2T";r(6.8[i],0)}6.L.13().2f(6.8[i])}6.1z=c.4c||X;6.2P=c.49||"";6.1Y=c.45||E.D.44.42;6.1X=c.41||15 E.D.2L(35,0);6.2e=c.3Y||S;6.2J=c.3W||"3U://D.3T.3R/3Q/3P/1W/3O.3N";6.Y=c.3M||15 E.D.2L(20,20);6.12=c.3K||{};6.12.1l=6.12.1l||"2H 1G 29 2E 2D";6.12.1G=6.12.1G||"2H 1l 29 2E 2D";6.I=H.1O("22");o(6.I.7,{1I:"2r 3H #3G"});o(6.I.7,c.3D);o(6.I.7,{1K:"21",W:"1c"});r(6.I);6.L.13().2f(6.I);6.1d=t(6.I);6.28=[E.D.J.19(H,"3B",B(e){b.2z(e)}),E.D.J.19(H,"3A",B(e){b.1U(e)}),E.D.J.19(6.8[0],"1E",B(e){b.1B(e)}),E.D.J.19(6.8[1],"1E",B(e){b.1B(e)}),E.D.J.19(6.8[2],"1E",B(e){b.1B(e)}),E.D.J.19(6.8[3],"1E",B(e){b.1B(e)}),E.D.J.19(H,"1E",B(e){b.2y(e)}),E.D.J.19(H,"3v",B(e){b.1T(e)}),E.D.J.19(H,"3t",B(e){b.2x(e)}),E.D.J.19(1R,"3r",s)];6.Z=X;6.1Q=X;6.1h=X;6.V=S;6.11=S;6.1p=S;6.1a=S;6.26=S;6.1j=S;A(6.1z){6.K=6.2s(6.1X);A(6.2e!==S){6.K.3o=6.2e}6.L.1W[6.1Y].3n(6.K);6.2q=6.L.1W[6.1Y].1e-1}};R.P.2s=B(a){9 b;9 c;9 d=6;b=H.1O("22");b.3l=6.2P;b.7.1K="3k";b.7.2j="2i";b.7.M=6.Y.M+"w";b.7.G=6.Y.G+"w";b.1q=6.12.1l;c=H.1O("3i");c.3g=6.2J;c.7.1K="21";c.7.C=-(6.Y.G*2)+"w";c.7.F=0+"w";b.2f(c);b.3m=B(e){d.Z=!d.Z;A(d.Z){d.K.1v.7.C=-(d.Y.G*0)+"w";d.K.1q=d.12.1G;d.23=1g;E.D.J.1k(d,"2p")}1f{d.K.1v.7.C=-(d.Y.G*2)+"w";d.K.1q=d.12.1l;E.D.J.1k(d,"2w")}d.1T(e)};b.3e=B(){d.K.1v.7.C=-(d.Y.G*1)+"w"};b.3d=B(){A(d.Z){d.K.1v.7.C=-(d.Y.G*0)+"w";d.K.1q=d.12.1G}1f{d.K.1v.7.C=-(d.Y.G*2)+"w";d.K.1q=d.12.1l}};b.3c=B(){N X};o(b.7,{2A:"3b",3x:a.M+"w",3y:a.G+"w"});N b};R.P.1S=B(e){9 a;e=e||1R.J;a=(e.39&&6.14==="1M")||(e.38&&6.14==="2G")||(e.33&&6.14==="2m");A(!a){2t(e.3F){1t 16:A(6.14==="1M"){a=1g}1w;1t 17:A(6.14==="2m"){a=1g}1w;1t 18:A(6.14==="2G"){a=1g}1w}}N a};R.P.2C=B(){9 c=6.26;A(c){9 b=6.1j;9 a=6.L.13();N c.C>b.C&&c.C<(b.C+a.2B)&&c.F>b.F&&c.F<(b.F+a.2l)}1f{N X}};R.P.2d=B(){9 i;A(6.L&&6.Z&&6.2C()){9 d=6.L.13();6.1p=d.2B-(6.T.C+6.T.1n);6.1a=d.2l-(6.T.F+6.T.1m);A(6.23){9 a=O(6.K.7.C,10)+6.1X.G;9 b=O(6.K.7.F,10)+6.1X.M;9 c=6.Y.G;9 e=6.Y.M;6.8[0].7.F="U";6.8[0].7.C="U";6.8[0].7.G=a+"w";6.8[0].7.M=6.1a+"w";6.8[1].7.F="U";6.8[1].7.C=(a+c)+"w";6.8[1].7.G=(6.1p-(a+c))+"w";6.8[1].7.M=6.1a+"w";6.8[2].7.F="U";6.8[2].7.C=a+"w";6.8[2].7.G=c+"w";6.8[2].7.M=b+"w";6.8[3].7.F=(b+e)+"w";6.8[3].7.C=a+"w";6.8[3].7.G=c+"w";6.8[3].7.M=(6.1a-(b+e))+"w";1b(i=0;i<6.8.1e;i++){6.8[i].7.W="2a"}}1f{6.8[0].7.C="U";6.8[0].7.F="U";6.8[0].7.G=6.1p+"w";6.8[0].7.M=6.1a+"w";1b(i=1;i<6.8.1e;i++){6.8[i].7.G="U";6.8[i].7.M="U"}1b(i=0;i<6.8.1e;i++){6.8[i].7.W="2a"}}}1f{1b(i=0;i<6.8.1e;i++){6.8[i].7.W="1c"}}};R.P.2z=B(e){A(6.L&&!6.Z&&6.1S(e)){6.1j=n(6.L.13());6.Z=1g;6.23=X;6.2d();E.D.J.1k(6,"2p")}A(6.1z&&6.1S(e)){6.K.7.W="1c"}};R.P.1H=B(e){9 a=q(e);9 p=15 E.D.1D();p.x=a.C-6.1j.C-6.T.C;p.y=a.F-6.1j.F-6.T.F;p.x=Q.1s(p.x,6.1p);p.y=Q.1s(p.y,6.1a);p.x=Q.1V(p.x,0);p.y=Q.1V(p.y,0);N p};R.P.1B=B(e){A(6.L&&6.Z){6.1j=n(6.L.13());6.1h=1g;6.V=6.11=6.1H(e);6.I.7.G=6.I.7.M="U";9 a=6.1C.2b();9 b=a.2c(6.V);A(6.1z){6.K.7.W="1c"}E.D.J.1k(6,"2X",b)}};R.P.2y=B(e){6.1Q=1g};R.P.1T=B(e){6.26=q(e);A(6.1h){6.11=6.1H(e);9 c=Q.1s(6.V.x,6.11.x);9 b=Q.1s(6.V.y,6.11.y);9 f=Q.1o(6.V.x-6.11.x);9 g=Q.1o(6.V.y-6.11.y);9 d=Q.1V(0,f-(6.1d.C+6.1d.1n));9 a=Q.1V(0,g-(6.1d.F+6.1d.1m));6.8[0].7.F="U";6.8[0].7.C="U";6.8[0].7.G=c+"w";6.8[0].7.M=6.1a+"w";6.8[1].7.F="U";6.8[1].7.C=(c+f)+"w";6.8[1].7.G=(6.1p-(c+f))+"w";6.8[1].7.M=6.1a+"w";6.8[2].7.F="U";6.8[2].7.C=c+"w";6.8[2].7.G=f+"w";6.8[2].7.M=b+"w";6.8[3].7.F=(b+g)+"w";6.8[3].7.C=c+"w";6.8[3].7.G=f+"w";6.8[3].7.M=(6.1a-(b+g))+"w";6.I.7.F=b+"w";6.I.7.C=c+"w";6.I.7.G=d+"w";6.I.7.M=a+"w";6.I.7.W="2a";E.D.J.1k(6,"29",15 E.D.1D(c,b+g),15 E.D.1D(c+f,b),6.1C.2b())}1f A(!6.1Q){6.1j=n(6.L.13());6.2d()}};R.P.2x=B(e){9 z;9 g=6;6.1Q=X;A(6.1h){A((6.1H(e).x===6.V.x)&&(6.1H(e).y===6.V.y)){6.1U(e);N}9 k=Q.1s(6.V.x,6.11.x);9 f=Q.1s(6.V.y,6.11.y);9 l=Q.1o(6.V.x-6.11.x);9 b=Q.1o(6.V.y-6.11.y);9 c=1g;A(c){k+=6.T.C;f+=6.T.F}9 m=6.1C.2b();9 d=m.2c(15 E.D.1D(k,f+b));9 j=m.2c(15 E.D.1D(k+l,f));9 h=15 E.D.2U(d,j);z=6.L.2I();6.L.2S(h);A(6.L.2I()<z){6.L.43(z)}9 a=m.2N(d);9 i=m.2N(j);A(c){a.x-=6.T.C;a.y-=6.T.F;i.x-=6.T.C;i.y-=6.T.F}6.I.7.C=a.x+"w";6.I.7.F=i.y+"w";6.I.7.G=(Q.1o(i.x-a.x)-(6.1d.C+6.1d.1n))+"w";6.I.7.M=(Q.1o(i.y-a.y)-(6.1d.F+6.1d.1m))+"w";2R(B(){g.I.7.W="1c"},4e);6.1h=X;6.1T(e);E.D.J.1k(6,"4d",h);A(!6.1S(e)){6.1U(e)}}};R.P.1U=B(e){9 i;A(6.L&&6.Z){6.Z=X;A(6.1h){6.I.7.W="1c";6.1h=X}1b(i=0;i<6.8.1e;i++){6.8[i].7.W="1c"}A(6.1z){6.K.1v.7.C=-(6.Y.G*2)+"w";6.K.1q=6.12.1l;6.K.7.W=""}E.D.J.1k(6,"2w")}};E.D.1Z.P.4b=B(a){6.1J=15 R(6,a)};E.D.1Z.P.4a=B(){9 i;9 d=6.1J;A(d){1b(i=0;i<d.28.1e;++i){E.D.J.48(d.28[i])}6.13().2O(d.I);1b(i=0;i<d.8.1e;i++){6.13().2O(d.8[i])}A(d.1z){6.1W[d.1Y].47(d.2q)}d.1C.2u(S);6.1J=S}};E.D.1Z.P.46=B(){N 6.1J!==S};E.D.1Z.P.4g=B(){N 6.1J}})();',62,266,'||||||this|style|veilDiv_|var|||||||||||||||||||||||px||||if|function|left|maps|google|top|width|document|boxDiv_|event|buttonDiv_|map_|height|return|parseInt|prototype|Math|DragZoom|null|borderWidths_|0px|startPt_|display|false|visualSize_|hotKeyDown_||endPt_|visualTips_|getDiv|key_|new||||addDomListener|mapHeight_|for|none|boxBorderWidths_|length|else|true|dragging_|typeof|mapPosn_|trigger|off|bottom|right|abs|mapWidth_|title|undefined|min|case|opacity|firstChild|break|documentElement|currentStyle|visualEnabled_|getComputedStyle|onMouseDown_|prjov_|Point|mousedown|defaultView|on|getMousePoint_|border|dragZoom_|position|posY|shift|scrollTop|createElement|scrollLeft|mouseDown_|window|isHotKeyDown_|onMouseMove_|onKeyUp_|max|controls|visualPositionOffset_|visualPosition_|Map||absolute|div|activatedByControl_|body||mousePosn_|backgroundColor|listeners_|drag|block|getProjection|fromContainerPixelToLatLng|setVeilVisibility_|visualPositionIndex_|appendChild|offsetTop|borderBottomWidth|hidden|overflow|offsetLeft|offsetHeight|ctrl|pageX|borderTopWidth|activate|controlIndex_|4px|initControl_|switch|setMap|init_|deactivate|onMouseUp_|onMouseDownDocument_|onKeyDown_|cursor|offsetWidth|isMouseOnMap_|mode|zoom|clientX|alt|Turn|getZoom|visualSprite_|offsetParent|Size|borderRightWidth|fromLatLngToContainerPixel|removeChild|visualClass_|borderLeftWidth|setTimeout|fitBounds|white|LatLngBounds|transparent|MozUserSelect|dragstart|default|veilStyle|paneStyle|clientY|crosshair|ctrlKey|gray||pageY|6px|altKey|shiftKey|onselectstart|pointer|ondragstart|onmouseout|onmouseover|thick|src|toLowerCase|img|key|relative|className|onclick|push|index|onRemove|draw|scroll|ownerDocument|mouseup|onAdd|mousemove|OverlayView|marginTop|marginLeft|medium|keyup|keydown|100|boxStyle|alpha|keyCode|736AFF|solid|filter|hasOwnProperty|visualTips|in|visualSize|png|dragzoom_btn|ftr|mapfiles|com|split|gstatic|http|2px|visualSprite|string|visualPositionIndex|WebkitTransform|MozTransform|visualPositionOffset|LEFT_TOP|setZoom|ControlPosition|visualPosition|keyDragZoomEnabled|removeAt|removeListener|visualClass|disableKeyDragZoom|enableKeyDragZoom|visualEnabled|dragend|1000|while|getDragZoomObject|thin'.split('|'),0,{}))
\ No newline at end of file diff --git a/protected/extensions/egmap/assets/latloncontrol.js b/protected/extensions/egmap/assets/latloncontrol.js new file mode 100644 index 0000000..e009e26 --- /dev/null +++ b/protected/extensions/egmap/assets/latloncontrol.js @@ -0,0 +1,81 @@ +/** +* LatLngControl class displays the LatLng and pixel coordinates +* underneath the mouse within a container anchored to it. +* @param {google.maps.Map} map Map to add custom control to. +*/ +function LatLngControl(map) { + /** + * Offset the control container from the mouse by this amount. + */ + this.ANCHOR_OFFSET_ = new google.maps.Point(8, 8); + + /** + * Pointer to the HTML container. + */ + this.node_ = this.createHtmlNode_(); + + // Add control to the map. Position is irrelevant. + map.controls[google.maps.ControlPosition.TOP].push(this.node_); + + // Bind this OverlayView to the map so we can access MapCanvasProjection + // to convert LatLng to Point coordinates. + this.setMap(map); + + // Register an MVC property to indicate whether this custom control + // is visible or hidden. Initially hide control until mouse is over map. + this.set('visible', false); + } + + // Extend OverlayView so we can access MapCanvasProjection. + LatLngControl.prototype = new google.maps.OverlayView(); + LatLngControl.prototype.draw = function() {}; + + /** + * @private + * Helper function creates the HTML node which is the control container. + * @return {HTMLDivElement} + */ + LatLngControl.prototype.createHtmlNode_ = function() { + var divNode = document.createElement('div'); + divNode.id = 'latlng-control'; + divNode.index = 100; + divNode.style.backgroundColor = "#ffc"; + divNode.style.border = "1px solid #676767"; + divNode.style.fontFamily = "arial, helvetica, sans-serif"; + divNode.style.fontSize = "0.7em"; + divNode.style.padding = "2px 4px"; + divNode.style.position = "absolute"; + return divNode; + }; + + /** + * MVC property's state change handler function to show/hide the + * control container. + */ + LatLngControl.prototype.visible_changed = function() { + this.node_.style.display = this.get('visible') ? '' : 'none'; + }; + + /** + * Specified LatLng value is used to calculate pixel coordinates and + * update the control display. Container is also repositioned. + * @param {google.maps.LatLng} latLng Position to display + */ + LatLngControl.prototype.updatePosition = function(latLng) { + var projection = this.getProjection(); + var point = projection.fromLatLngToContainerPixel(latLng); + + // Update control position to be anchored next to mouse position. + this.node_.style.left = point.x + this.ANCHOR_OFFSET_.x + 'px'; + this.node_.style.top = point.y + this.ANCHOR_OFFSET_.y + 'px'; + + // Update control to display latlng and coordinates. + this.node_.innerHTML = [ + latLng.toUrlValue(4), + '<br/>', + point.x, + 'px, ', + point.y, + 'px' + ].join(''); +};
\ No newline at end of file diff --git a/protected/extensions/egmap/assets/markerclusterer_packed.js b/protected/extensions/egmap/assets/markerclusterer_packed.js new file mode 100644 index 0000000..9ef8385 --- /dev/null +++ b/protected/extensions/egmap/assets/markerclusterer_packed.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('(5(){7 d=32,f=33,g=34;5 j(a){8 5(b){3[a]=b}}5 k(a){8 5(){8 3[a]}}7 l;5 m(a,b,c){3.1f(m,13.12.22);3.b=a;3.a=[];3.m=[];3.$=[31,2X,2Y,35,3c];3.i=[];3.z=g;c=c||{};3.f=c.3b||37;3.V=c.1A||f;3.i=c.39||[];3.U=c.2V||3.O;3.T=c.2K||3.N;3.M=d;6(c.23!=25)3.M=c.23;3.p=g;6(c.21!=25)3.p=c.21;n(3);3.18(a);3.I=3.b.1t();7 e=3;13.12.1m.1x(3.b,"2M",5(){7 h=e.b.1P[e.b.1R()].1A,o=e.b.1t();6(!(o<0||o>h))6(e.I!=o){e.I=e.b.1t();e.k()}});13.12.1m.1x(3.b,"2U",5(){e.h()});b&&b.14&&3.B(b,g)}l=m.4;l.O="3E://13-12-3C-3B-3G.3M.3H/3I/3x/3l/3m/m";l.N="3k";l.1f=5(a,b){8 5(c){15(7 e 3g c.4)3.4[e]=c.4[e];8 3}.2D(a,[b])};l.1j=5(){6(!3.z){3.z=d;q(3)}};l.1k=5(){};5 n(a){6(!a.i.14)15(7 b=0,c;c=a.$[b];b++)a.i.16({1B:a.U+(b+1)+"."+a.T,1c:c,1l:c})}l.w=k("i");l.q=k("a");l.S=5(){8 3.a.14};l.H=5(){8 3.V||3.b.1P[3.b.1R()].1A};l.F=5(a,b){15(7 c=0,e=a.14,h=e;h!==0;){h=1y(h/10,10);c++}c=9.24(c,b);8{1e:e,1C:c}};l.Y=j("F");l.G=k("F");l.B=5(a,b){15(7 c=0,e;e=a[c];c++)t(3,e);b||3.h()};5 t(a,b){b.1g(g);b.18(f);b.r=g;b.2s&&13.12.1m.1x(b,"2t",5(){b.r=g;a.k();a.h()});a.a.16(b)}l.o=5(a,b){t(3,a);b||3.h()};5 u(a,b){7 c=-1;6(a.a.1n)c=a.a.1n(b);17 15(7 e=0,h;h=a.a[e];e++)6(h==b){c=e;27}6(c==-1)8 g;a.a.2z(c,1);b.1g(g);b.18(f);8 d}l.W=5(a,b){7 c=u(3,a);6(!b&&c){3.k();3.h();8 d}17 8 g};l.X=5(a,b){15(7 c=g,e=0,h;h=a[e];e++){h=u(3,h);c=c||h}6(!b&&c){3.k();3.h();8 d}};l.R=5(){8 3.m.14};l.1d=k("b");l.18=j("b");l.v=k("f");l.Z=j("f");l.u=5(a){7 b=3.1X(),c=1a 13.12.1F(a.1I().19(),a.1I().1i()),e=1a 13.12.1F(a.1J().19(),a.1J().1i());c=b.1v(c);c.x+=3.f;c.y-=3.f;e=b.1v(e);e.x-=3.f;e.y+=3.f;c=b.1Z(c);b=b.1Z(e);a.1f(c);a.1f(b);8 a};l.P=5(){3.k();3.a=[]};l.k=5(){15(7 a=0,b;b=3.m[a];a++)b.1p();15(a=0;b=3.a[a];a++){b.r=g;b.18(f);b.1g(g)}3.m=[]};l.h=5(){q(3)};5 q(a){6(a.z)15(7 b=a.u(1a 13.12.1z(a.b.1r().1J(),a.b.1r().1I())),c=0,e;e=a.a[c];c++)6(!e.r&&b.26(e.1b())){7 h=a;e=e;15(7 o=3h,r=f,x=0,p=2c 0;p=h.m[x];x++){7 i=p.1u();6(i){i=i;7 s=e.1b();6(!i||!s)i=0;17{7 y=(s.19()-i.19())*9.1q/1o,z=(s.1i()-i.1i())*9.1q/1o;i=9.1s(y/2)*9.1s(y/2)+9.2b(i.19()*9.1q/1o)*9.2b(s.19()*9.1q/1o)*9.1s(z/2)*9.1s(z/2);i=2h*2*9.2g(9.2a(i),9.2a(1-i))}6(i<o){o=i;r=p}}}6(r&&r.D.26(e.1b()))r.o(e);17{p=1a v(h);p.o(e);h.m.16(p)}}}5 v(a){3.j=a;3.b=a.1d();3.f=a.v();3.p=a.p;3.d=f;3.a=[];3.D=f;3.l=1a w(3,a.w(),a.v())}l=v.4;l.o=5(a){7 b;a:6(3.a.1n)b=3.a.1n(a)!=-1;17{b=0;15(7 c;c=3.a[b];b++)6(c==a){b=d;27 a}b=g}6(b)8 g;6(3.d){6(3.p){c=3.a.14+1;b=(3.d.19()*(c-1)+a.1b().19())/c;c=(3.d.1i()*(c-1)+a.1b().1i())/c;3.d=1a 13.12.1F(b,c);A(3)}}17{3.d=a.1b();A(3)}6(3.a.14==0){a.18(3.b);a.1g(d)}17 6(3.a.14==1){3.a[0].18(f);3.a[0].1g(g)}a.r=d;3.a.16(a);6(3.b.1t()>3.j.H())15(a=0;b=3.a[a];a++){b.18(3.b);b.1g(d)}17 6(3.a.14<2)B(3.l);17{b=3.j.G()(3.a,3.j.w().14);3.l.20(3.d);a=3.l;a.A=b;a.2i=b.1e;a.2e=b.1C;6(a.c)a.c.1Y=b.1e;b=9.2j(0,a.A.1C-1);b=9.24(a.i.14-1,b);b=a.i[b];a.L=b.1B;a.g=b.1c;a.n=b.1l;a.J=b.2d;a.e=b.2x;a.K=b.2k;a.C=b.2v;3.l.1W()}8 d};l.1r=5(){15(7 a=1a 13.12.1z(3.d,3.d),b=3.q(),c=0,e;e=b[c];c++)a.1f(e.1b());8 a};l.1p=5(){3.l.1p();3.a.14=0;2y 3.a};l.Q=5(){8 3.a.14};l.q=k("a");l.1u=k("d");5 A(a){a.D=a.j.u(1a 13.12.1z(a.d,a.d))}l.1d=k("b");5 w(a,b,c){a.j.1f(w,13.12.22);3.i=b;3.2B=c||0;3.t=a;3.d=f;3.b=a.1d();3.A=3.c=f;3.s=g;3.18(3.b)}l=w.4;l.1j=5(){3.c=1Q.2A("2u");6(3.s){3.c.1h.1M=C(3,D(3,3.d));3.c.1Y=3.A.1e}3.2n().2m.2l(3.c);7 a=3;13.12.1m.2o(3.c,"2p",5(){7 b=a.t.j;13.12.1m.2q(b,"2w",a.t);b.M&&a.b.2r(a.t.1r())})};5 D(a,b){7 c=a.1X().1v(b);c.x-=1y(a.n/2,10);c.y-=1y(a.g/2,10);8 c}l.1k=5(){6(3.s){7 a=D(3,3.d);3.c.1h.1D=a.y+"E";3.c.1h.1G=a.x+"E"}};5 B(a){6(a.c)a.c.1h.1N="2C";a.s=g}l.1W=5(){6(3.c){3.c.1h.1M=C(3,D(3,3.d));3.c.1h.1N=""}3.s=d};l.1p=5(){3.18(f)};l.1E=5(){6(3.c&&3.c.1O){B(3);3.c.1O.2f(3.c);3.c=f}};l.20=j("d");5 C(a,b){7 c=[];6(1Q.3r)c.16(\'3q:3p:3s.3t.3v(3u=3o,3n="\'+a.L+\'");\');17{c.16("1S-3i:1B("+a.L+");");c.16("1S-28:"+(a.C?a.C:"0 0")+";")}6(1H a.e==="3j"){1H a.e[0]==="1V"&&a.e[0]>0&&a.e[0]<a.g?c.16("1c:"+(a.g-a.e[0])+"E; 1U-1D:"+a.e[0]+"E;"):c.16("1c:"+a.g+"E; 1T-1c:"+a.g+"E;");1H a.e[1]==="1V"&&a.e[1]>0&&a.e[1]<a.n?c.16("1l:"+(a.n-a.e[1])+"E; 1U-1G:"+a.e[1]+"E;"):c.16("1l:"+a.n+"E; 1e-1K:1L;")}17 c.16("1c:"+a.g+"E; 1T-1c:"+a.g+"E; 1l:"+a.n+"E; 1e-1K:1L;");c.16("3w:3A; 1D:"+b.y+"E; 1G:"+b.x+"E; 3L:"+(a.J?a.J:"3F")+"; 28:3z; 1w-3y:"+(a.K?a.K:11)+"E; 1w-3D:3J,3K-3f; 1w-3e:2Q");8 c.2P("")}2O.2R=m;m.4.2S=m.4.o;m.4.2T=m.4.B;m.4.2N=m.4.P;m.4.2G=m.4.G;m.4.2F=m.4.v;m.4.2E=m.4.u;m.4.1d=m.4.1d;m.4.29=m.4.q;m.4.2H=m.4.H;m.4.2I=m.4.w;m.4.2L=m.4.R;m.4.2J=m.4.S;m.4.2W=m.4.h;m.4.38=m.4.W;m.4.3a=m.4.X;m.4.3d=m.4.k;m.4.36=m.4.Y;m.4.2Z=m.4.Z;m.4.1j=m.4.1j;m.4.1k=m.4.1k;v.4.1u=v.4.1u;v.4.30=v.4.Q;v.4.29=v.4.q;w.4.1j=w.4.1j;w.4.1k=w.4.1k;w.4.1E=w.4.1E})();',62,235,'|||this|prototype|function|if|var|return|Math|||||||||||||||||||||||||||||||px||||||||||||||||||||||||maps|google|length|for|push|else|setMap|lat|new|getPosition|height|getMap|text|extend|setVisible|style|lng|onAdd|draw|width|event|indexOf|180|remove|PI|getBounds|sin|getZoom|getCenter|fromLatLngToDivPixel|font|addListener|parseInt|LatLngBounds|maxZoom|url|index|top|onRemove|LatLng|left|typeof|getNorthEast|getSouthWest|align|center|cssText|display|parentNode|mapTypes|document|getMapTypeId|background|line|padding|number|show|getProjection|innerHTML|fromDivPixelToLatLng|setCenter|averageCenter|OverlayView|zoomOnClick|min|undefined|contains|break|position|getMarkers|sqrt|cos|void|textColor|aa|removeChild|atan2|6371|ca|max|textSize|appendChild|overlayImage|getPanes|addDomListener|click|trigger|fitBounds|draggable|dragend|DIV|backgroundPosition|clusterclick|anchor|delete|splice|createElement|ba|none|apply|getExtendedBounds|getGridSize|getCalculator|getMaxZoom|getStyles|getTotalMarkers|imageExtension|getTotalClusters|zoom_changed|clearMarkers|window|join|bold|MarkerClusterer|addMarker|addMarkers|idle|imagePath|redraw|56|66|setGridSize|getSize|53|true|null|false|78|setCalculator|60|removeMarker|styles|removeMarkers|gridSize|90|resetViewport|weight|serif|in|4E4|image|object|png|markerclusterer|images|src|scale|progid|filter|all|DXImageTransform|Microsoft|sizingMethod|AlphaImageLoader|cursor|trunk|size|absolute|pointer|library|utility|family|http|black|v3|com|svn|Arial|sans|color|googlecode'.split('|'),0,{})) diff --git a/protected/extensions/egmap/assets/markers/m1.png b/protected/extensions/egmap/assets/markers/m1.png Binary files differnew file mode 100644 index 0000000..329ff52 --- /dev/null +++ b/protected/extensions/egmap/assets/markers/m1.png diff --git a/protected/extensions/egmap/assets/markers/m2.png b/protected/extensions/egmap/assets/markers/m2.png Binary files differnew file mode 100644 index 0000000..b999cbc --- /dev/null +++ b/protected/extensions/egmap/assets/markers/m2.png diff --git a/protected/extensions/egmap/assets/markers/m3.png b/protected/extensions/egmap/assets/markers/m3.png Binary files differnew file mode 100644 index 0000000..9f30b30 --- /dev/null +++ b/protected/extensions/egmap/assets/markers/m3.png diff --git a/protected/extensions/egmap/assets/markers/m4.png b/protected/extensions/egmap/assets/markers/m4.png Binary files differnew file mode 100644 index 0000000..0d3f826 --- /dev/null +++ b/protected/extensions/egmap/assets/markers/m4.png diff --git a/protected/extensions/egmap/assets/markers/m5.png b/protected/extensions/egmap/assets/markers/m5.png Binary files differnew file mode 100644 index 0000000..61387d2 --- /dev/null +++ b/protected/extensions/egmap/assets/markers/m5.png diff --git a/protected/extensions/egmap/assets/markerwithlabel_packed.js b/protected/extensions/egmap/assets/markerwithlabel_packed.js new file mode 100644 index 0000000..c8e2493 --- /dev/null +++ b/protected/extensions/egmap/assets/markerwithlabel_packed.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('8 t(a){2.3=a;2.6=X.1v("1V");2.6.4.L="R: 1g; 15: 1A;";2.p=X.1v("1V");2.p.4.L=2.6.4.L;2.p.23("2L","1Q w;");2.p.23("2w","1Q w;");2.v=X.1v("2o");2.v.4.L="R: 1g; z-2l: 2g; I: 16;";2.v.4.1b="-2a";2.v.4.1w="-2Y";2.v.2V="22://5.1X.1T/1R/1P/1M/2x.2v"}t.s=W 7.5.2n();t.s.2m=8(){r g=2;r l=w;r c=w;r o;r f;r i,12;r n;r d;r m=20;r h="29(22://5.1X.1T/1R/1P/1M/28.27)";r j=8(e){9(e.24){e.24()}e.2R=G;9(e.1Z){e.1Z()}};r k=8(){g.3.1W(2J)};2.1n().1S.S(2.6);2.1n().2D.S(2.p);2.1n().1S.S(2.v);2.1p=[7.5.q.M(2.p,"1N",8(e){9(g.3.N()||g.3.U()){2.4.19="1Y";7.5.q.B(g.3,"1N",e)}}),7.5.q.M(2.p,"1U",8(e){9((g.3.N()||g.3.U())&&!c){2.4.19=g.3.2r();7.5.q.B(g.3,"1U",e)}}),7.5.q.M(2.p,"1J",8(e){i=0;12=0;c=w;9(g.3.N()){l=G;2.4.19=h}9(g.3.N()||g.3.U()){7.5.q.B(g.3,"1J",e)}j(e)}),7.5.q.M(X,"1G",8(a){r b;9(l){l=w;g.p.4.19="1Y";7.5.q.B(g.3,"1G",a)}9(c){a.E=o;n=G;9(d){b=g.Q().1i(g.3.11());b.y+=m;g.3.J(g.Q().1E(b));2k{g.3.1W(7.5.2j.2i);2h(k,2f)}2e(e){}g.v.4.I="16"}g.3.T(f);c=w;7.5.q.B(g.3,"1D",a)}}),7.5.q.u(g.3.2d(),"2c",8(a){r b;9(l){a.E=W 7.5.2b(a.E.1d()-i,a.E.1c()-12);9(c){o=a.E;b=g.Q().1i(a.E);9(d){g.v.4.Y=b.x+"A";g.v.4.P=b.y+"A";g.v.4.I="";b.y-=m}g.3.J(g.Q().1E(b));9(d){g.p.4.P=(b.y+m)+"A"}7.5.q.B(g.3,"1C",a)}V{i=a.E.1d()-g.3.11().1d();12=a.E.1c()-g.3.11().1c();f=g.3.1a();g.3.T(1B);d=g.3.D("14");c=G;7.5.q.B(g.3,"1z",a)}}}),7.5.q.M(2.p,"1y",8(e){9(g.3.N()||g.3.U()){9(n){n=w}V{7.5.q.B(g.3,"1y",e);j(e)}}}),7.5.q.M(2.p,"1x",8(e){9(g.3.N()||g.3.U()){7.5.q.B(g.3,"1x",e);j(e)}}),7.5.q.u(2.3,"1z",8(a){9(!c){d=2.D("14")}}),7.5.q.u(2.3,"1C",8(a){9(!c){9(d){g.J(m);g.6.4.K=1B+(2.D("18")?-1:+1)}}}),7.5.q.u(2.3,"1D",8(a){9(!c){9(d){g.J(0)}}}),7.5.q.u(2.3,"2X",8(){g.J()}),7.5.q.u(2.3,"2W",8(){g.T()}),7.5.q.u(2.3,"2U",8(){g.17()}),7.5.q.u(2.3,"2T",8(){g.17()}),7.5.q.u(2.3,"2S",8(){g.1t()}),7.5.q.u(2.3,"2Q",8(){g.1f()}),7.5.q.u(2.3,"2P",8(){g.1e()}),7.5.q.u(2.3,"2O",8(){g.Z()}),7.5.q.u(2.3,"2M",8(){g.Z()})]};t.s.2K=8(){r i;2.6.1r.1h(2.6);2.p.1r.1h(2.p);2.v.1r.1h(2.v);26(i=0;i<2.1p.2I;i++){7.5.q.2G(2.1p[i])}};t.s.2F=8(){2.1f();2.1t();2.Z()};t.s.1f=8(){r a=2.3.D("1j");9(F a.2E==="H"){2.6.13=a;2.p.13=2.6.13}V{2.6.13="";2.6.S(a);a=a.2C(G);2.p.S(a)}};t.s.1t=8(){2.p.2B=2.3.2A()||""};t.s.Z=8(){r i,C;2.6.1o=2.3.D("1m");2.p.1o=2.6.1o;2.6.4.L="";2.p.4.L="";C=2.3.D("C");26(i 2z C){9(C.2y(i)){2.6.4[i]=C[i];2.p.4[i]=C[i]}}2.1L()};t.s.1L=8(){2.6.4.R="1g";2.6.4.15="1A";9(F 2.6.4.O!=="H"&&2.6.4.O!==""){2.6.4.1K="1O(O="+(2.6.4.O*2u)+")"}2.p.4.R=2.6.4.R;2.p.4.15=2.6.4.15;2.p.4.O=0.2H;2.p.4.1K="1O(O=1)";2.1e();2.J();2.17()};t.s.1e=8(){r a=2.3.D("1q");2.6.4.1b=-a.x+"A";2.6.4.1w=-a.y+"A";2.p.4.1b=-a.x+"A";2.p.4.1w=-a.y+"A"};t.s.J=8(a){r b=2.Q().1i(2.3.11());9(F a==="H"){a=0}2.6.4.Y=b.x+"A";2.6.4.P=(b.y-a)+"A";2.p.4.Y=2.6.4.Y;2.p.4.P=2.6.4.P;2.T()};t.s.T=8(){r a=(2.3.D("18")?-1:+1);9(F 2.3.1a()==="H"){2.6.4.K=2t(2.6.4.P,10)+a;2.p.4.K=2.6.4.K}V{2.6.4.K=2.3.1a()+a;2.p.4.K=2.6.4.K}};t.s.17=8(){9(2.3.D("1l")){2.6.4.I=2.3.2s()?"2N":"16"}V{2.6.4.I="16"}2.p.4.I=2.6.4.I};8 1k(a){a=a||{};a.1j=a.1j||"";a.1q=a.1q||W 7.5.2q(0,0);a.1m=a.1m||"2p";a.C=a.C||{};a.18=a.18||w;9(F a.1l==="H"){a.1l=G}9(F a.14==="H"){a.14=G}9(F a.21==="H"){a.21=G}9(F a.1I==="H"){a.1I=w}2.1H=W t(2);7.5.1s.25(2,1F)}1k.s=W 7.5.1s();1k.s.1u=8(a){7.5.1s.s.1u.25(2,1F);2.1H.1u(a)};',62,185,'||this|marker_|style|maps|labelDiv_|google|function|if||||||||||||||||eventDiv_|event|var|prototype|MarkerLabel_|addListener|crossDiv_|false||||px|trigger|labelStyle|get|latLng|typeof|true|undefined|display|setPosition|zIndex|cssText|addDomListener|getDraggable|opacity|top|getProjection|position|appendChild|setZIndex|getClickable|else|new|document|left|setStyles||getPosition|cLngOffset|innerHTML|raiseOnDrag|overflow|none|setVisible|labelInBackground|cursor|getZIndex|marginLeft|lng|lat|setAnchor|setContent|absolute|removeChild|fromLatLngToDivPixel|labelContent|MarkerWithLabel|labelVisible|labelClass|getPanes|className|listeners_|labelAnchor|parentNode|Marker|setTitle|setMap|createElement|marginTop|dblclick|click|dragstart|hidden|1000000|drag|dragend|fromDivPixelToLatLng|arguments|mouseup|label|draggable|mousedown|filter|setMandatoryStyles|mapfiles|mouseover|alpha|en_us|return|intl|overlayImage|com|mouseout|div|setAnimation|gstatic|pointer|stopPropagation||clickable|http|setAttribute|preventDefault|apply|for|cur|closedhand_8_8|url|8px|LatLng|mousemove|getMap|catch|1406|1000002|setTimeout|BOUNCE|Animation|try|index|onAdd|OverlayView|img|markerLabels|Point|getCursor|getVisible|parseInt|100|png|ondragstart|drag_cross_67_16|hasOwnProperty|in|getTitle|title|cloneNode|overlayMouseTarget|nodeType|draw|removeListener|01|length|null|onRemove|onselectstart|labelstyle_changed|block|labelclass_changed|labelanchor_changed|labelcontent_changed|cancelBubble|title_changed|labelvisible_changed|visible_changed|src|zindex_changed|position_changed|9px'.split('|'),0,{}))
\ No newline at end of file diff --git a/protected/extensions/egmap/kml/EGMapKMLFeed.php b/protected/extensions/egmap/kml/EGMapKMLFeed.php new file mode 100644 index 0000000..f787225 --- /dev/null +++ b/protected/extensions/egmap/kml/EGMapKMLFeed.php @@ -0,0 +1,394 @@ +<?php +/** + * + * EGMapKMLFeed Class + * + * KML Feed Creator + * + * @author Antonio Ramirez Cobos + * @link www.ramirezcobos.com + * + * + * @copyright + * + * Copyright (c) 2010 Antonio Ramirez Cobos + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +/** + * + * List of currently supported KML tags by Google Maps v3 + * ---------------------------------------------- + * <kml> + * <atom:author> + * <atom:link> + * <atom:name> + * ----------------------------------------------- + * Example + * ------------------------------------------------ + <Document> + <atom:author> + <atom:name>J. K. Rowling</atom:name> + </atom:author> + <atom:link href="http://www.harrypotter.com" /> + <Style id="myStyleId"></Style> + <Placemark></Placemark> + </Document> + ------------------------------------------------ + * <Placemark> + * <styleUrl> + * <name> + * <description> + * <Point> + * <coordinates> + * ------------------------------------------------ + * Example + * ------------------------------------------------ + <Placemark> + <styleUrl>#myIconStyleID</styleUrl> + <name> + <description> + <![CDATA[ + This is an image + <img src="icon.jpg"> + and we have a link http://www.google.com. + ]]> + </description> + <Point> + <coordinates>-90.86948943473118,48.25450093195546</coordinates> + </Point> + </Placemark> + * ------------------------------------------------ + * <Style> + * <IconStyle id="myIconStyleID> + * <Icon> + * <PolyStyle id="myPolyStyleID"> + * <color> + * <colorMode> + * <LineStyle> + * <color> + * <width> + * + * + * ------------------------------------------------ + * Examples + * ------------------------------------------------ + <Document> + <Style id="restaurantStyle"> + <IconStyle id="restuarantIcon"> + <Icon> + <href>http://maps.google.com/mapfiles/kml/pal2/icon63.png</href> + </Icon> + </IconStyle> + </Style> + ------------------------------------------------ + <Style id="examplePolyStyle"> + <PolyStyle> + <color>ff0000cc</color> + <colorMode>random</colorMode> + </PolyStyle> + </Style> + ------------------------------------------------ + <Style id="linestyleExample"> + <LineStyle> + <color>7f0000ff</color> + <width>4</width> + </LineStyle> + </Style> + </Document> + * ------------------------------------------------ + * <LatLonBox> + * <north> + * <south> + * <east> + * <west> + * ------------------------------------------------ + * Example + * ------------------------------------------------ + <Document> + <LatLonBox> + <north>48.25475939255556</north> + <south>48.25207367852141</south> + <east>-90.86591508839973</east> + <west>-90.8714285289695</west> + </LatLonBox> + </Document> + ------------------------------------------------ + * <NetworkLink> + * <Link> + * <refreshMode> + * <refreshInterval> + * <viewRefreshTime> + * ------------------------------------------------ + * Example + * ------------------------------------------------ + <Document> + <NetworkLink> + <name>NE US Radar</name> + <Link> + <href>http://www.example.com/geotiff/NE/MergedReflectivityQComposite.kml</href> + <refreshMode>onInterval</refreshMode> // headers HTTP only compatible with mode "onExpire" + <refreshInterval>30</refreshInterval> + <viewRefreshMode>onStop</viewRefreshMode> + <viewRefreshTime>7</viewRefreshTime> + </Link> + </NetworkLink> + </Document> + * ------------------------------------------------ + * <Polygon> + * <outerBoundaryIs> + * <LinearRing> + * <coordinates> + * <LineString> + * <coordinates> + * ------------------------------------------------ + * Example + * ------------------------------------------------ + <Placemark> + <Polygon> + <innerBoundaryIs> // only supported here + <LinearRing> + <coordinates> + -122.366212,37.818977,30 + -122.365424,37.819294,30 + </coordinates> + </LinearRing> + </innerBoundaryIs> + </Polygon> + </Placemark> + <Placemark> + <name>unextruded</name> + <LineString> + <coordinates> + -122.364383,37.824664,0 -122.364152,37.824322,0 + </coordinates> + </LineString> + </Placemark> + ------------------------------------------------ + * Other supported tags by Google Maps v3 + * <range> + * <ScreenOverlay> + * <size> + * <Snippet> + * <value> + * <longitude> + * <open> + * <outline> + * <expires> + * <fill> + * <heading> + * <hotSpot> + * <latitude> + */ +class EGMapKMLFeed { + /** + * + * Holds all tags on the feed + * @var unknown_type + */ + protected $elements; + + const STYLE_ICON = 'Icon'; // when using addStyle Array it specifies is an IconStyle + const STYLE_LINE = 'Line'; // when using addStyle Array it specifies is an LineStyle + const STYLE_POLY = 'Poly'; // when using addStyle Array it specifies is an PolyStyle + /** + * + * constructor + */ + function __construct(){ + $this->elements = new CMap(); + } + /** + * + * ATOM style author + * @param string $name + */ + public function setAuthor( $name ){ + if( null === $this->elements->itemAt('head') ) + $this->elements->add('head', new CMap() ); + $item = '<atom:author><atom:name>'.$name.'</atom:name></atom:author>'; + + $this->elements->itemAt('head')->add('author', $item); + + } + /** + * + * ATOM style link + * @param string $url + */ + public function setLink( $url ){ + if( null === $this->elements->itemAt('head') ) + $this->elements->add('head', new CMap() ); + $validator = new CUrlValidator(); + if(!$validator->validateValue($url)) + throw new CException( Yii::t('EGMap', 'EGMapKMLFeed.setLink Url does not seem to valid') ); + $item = '<atom:link href="'.$url.'" />'; + $this->elements->itemAt('head')->add('link', $item); + } + /** + * + * Adding an externally created Tag at the end of its 'body' section + * Note: this method does not validates the tag + * @param EGMapKMLNode $tag + * @return string id of the inserted Tag + */ + public function addTag( EGMapKMLNode $tag ){ + if( null === $this->elements->itemAt('body') ) + $this->elements->add('body', new CMap() ); + + $name = uniqid(); + + $this->elements->itemAt('body')->add(uniqid(), $tag->toXML()); + + return $name; + } + /** + * + * Removes inserted tag name from specific section + * sections can be head, body, styles, and placemark + * @param string $tagName to be removed + * @param string $section where to remove the tag + */ + public function removeTag( $tagName, $section ){ + foreach($this->elements as $map) + { + if($map->itemAt($section)){ + $map->itemAt($section)->remove($tagName); + return true; + } + } + return false; + } + /** + * + * This method is to add style tags as arrays + * the style nodes are represented as the following: + * <pre> + * // Icon + * $nodes = array( 'href'=>'http://url'); + * // Line + * $nodes = array( 'color'=>'#FFAA00','width'=>2); + * // Polyline + * $nodes = array( 'color'=>'#FFAA00','colorMode'=>'random' ); + * </pre> + * @param string $styleId id of the style + * @param string $styleType the type of the style + * @param array $nodes the tags to insert + */ + public function addStyleArray( $styleId, $styleType = self::STYLE_ICON, $nodes = array() ){ + $item = '<Style id="'.$styleId.'">'; + switch ($styleType){ + case self::STYLE_ICON: + case self::STYLE_LINE: + case self::STYLE_POLY: + $item .= CHtml::openTag($styleType.'Style'); + break; + default: + throw new CException( Yii::t('EGMap','KML Style not supported') ); + } + $item .= $this->batchNodeCreate($nodes); + + $item .= CHtml::closeTag($styleType.'Style'); + $item .= '</Style>'; + + if( null === $this->elements->itemAt('styles') ) + $this->elements->add( 'styles', new CMap() ); + + $this->elements->itemAt('styles')->add( $styleId, $item ); + } + /** + * Adds a placemark on array structure + * Example: + * <pre> + * $nodes = array( + * 'name'=>array('content'=>'testing'), + * 'description'=>array('content'=>'This marker has <b>HTML</b>'), + * 'styleUrl'=>array('content'=>'#style2'), + * 'Point'=>array('children'=>array( + * 'coordinates'=>array('content'=>'2.9087440013885635,39.719588117933185,0')))); + * + * $kml->addPlacemark($nodes); + * </pre> + * @param array $nodes the tags to insert + */ + public function addPlacemarkArray( $nodes = array() ){ + $item = '<Placemark>'; + + $item .= $this->batchNodeCreate($nodes); + + $item .= '</Placemark>'; + + if( null === $this->elements->itemAt('body') ) + $this->elements->add( 'body', new CMap() ); + + $name = uniqid(); + + $this->elements->itemAt('body')->add( $name, $item ); + + return $name; + + } + /** + * + * Converts array given tags to its XML representation + * Note: It does not check for correct array structure + * + * @param array $tags + */ + public function batchNodeCreate( $tags ){ + $result = ''; + if(is_array( $tags) ){ + foreach($tags as $tag=>$el){ + $result .= CHtml::openTag($tag, (isset($el['attributes']) && is_array($el['attributes'])? $el['attributes']:array())); + $result .= isset($el['content'])? ($tag=='description'? '<![CDATA['. $el['content'].']]>': $el['content']) : ''; + $result .= isset($el['children']) && is_array($el['children'])? $this->batchNodeCreate($el['children']) : ''; + $result .= CHtml::closeTag($tag); + } + } + return $result; + } + /** + * + * Generates the feed + */ + public function generateFeed( ){ + // you can choose between the both, as both of them work correctly + // Google Earth MIME/TYPE + // header('Content-type: application/vnd.google-earth.kml+xml'); + header("Content-type: text/xml"); + + echo '<kml xmlns="http://earth.google.com/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom">'; + echo '<Document>'; + $this->renderItems(array('head', 'body','styles','placemarks')); + echo '</Document>'; + echo '</kml>'; + } + /** + * + * Render tags by sections + * @param array | string sections to render $sections + */ + public function renderItems( $sections ){ + + if(!is_array($sections)) $sections = array( $sections ); + + foreach( $sections as $section ){ + if(null === $this->elements->itemAt($section)) continue; + + foreach($this->elements->itemAt($section) as $tag) + echo $tag; + } + } +} diff --git a/protected/extensions/egmap/kml/EGMapKMLIconStyle.php b/protected/extensions/egmap/kml/EGMapKMLIconStyle.php new file mode 100644 index 0000000..1ca1779 --- /dev/null +++ b/protected/extensions/egmap/kml/EGMapKMLIconStyle.php @@ -0,0 +1,74 @@ +<?php +/** + * + * EGMapKMLIconStyle Class + * + * KML Icon Style tag object + * + * @author Antonio Ramirez Cobos + * @link www.ramirezcobos.com + * + * + * @copyright + * + * Copyright (c) 2010 Antonio Ramirez Cobos + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +class EGMapKMLIconStyle extends EGMapKMLNode { + /** + * + * Style id + * @var string + */ + public $id; + /** + * + * Url of the image + * Must be an absolute URL + * @var string + */ + public $href; + /** + * + * Class constructor + * @param string $id style id + * @param string $iconId icon id + * @param string $href absolute URL of the image + */ + public function __construct($id, $iconId = null, $href = null){ + + $this->tag = 'IconStyle'; + $this->id = $id; + $this->tagId = $iconId; + $this->href = $href; + } + /** + * (non-PHPdoc) + * @see EGMapKMLNode::toXML() + */ + public function toXML(){ + + $icon = new EGMapKMLNode('Icon'); + if(!is_null($this->href)) + $icon->addChild( new EGMapKMLNode('href', $this->href ) ); + $this->addChild($icon); + $result = CHtml::openTag( 'Style', array( 'id'=>$this->id ) ); + $result .= parent::toXML(); + $result .= CHtml::closeTag('Style'); + + return $result; + } +}
\ No newline at end of file diff --git a/protected/extensions/egmap/kml/EGMapKMLLineString.php b/protected/extensions/egmap/kml/EGMapKMLLineString.php new file mode 100644 index 0000000..79b8bd0 --- /dev/null +++ b/protected/extensions/egmap/kml/EGMapKMLLineString.php @@ -0,0 +1,86 @@ +<?php +/** + * + * EGMapKMLLineString Class + * + * KML LineString tag object + * + * Defines a connected set of line segments. Use <LineStyle> to specify the color, color mode, and width + * of the line. When a LineString is extruded, the line is extended to the ground, forming a polygon that + * looks somewhat like a wall or fence. For extruded LineStrings, the line itself uses the current LineStyle, + * and the extrusion uses the current PolyStyle. + * + * @author Antonio Ramirez Cobos + * @link www.ramirezcobos.com + * + * + * @copyright + * + * Copyright (c) 2010 Antonio Ramirez Cobos + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +class EGMapKMLLineString extends EGMapKMLNode{ + /** + * + * Two or more coordinate tuples, each consisting of floating point values for longitude, latitude, and + * altitude. The altitude component is optional. Insert a space between tuples. + * Do not include spaces within a tuple. + * @var array + */ + protected $coordinates = array(); + /** + * + * Class constructor + * @param array $coordinates + */ + public function __construct( $coordinates = array() ){ + $this->tag = 'LineString'; + if(is_array($coordinates)) $this->coordinates = $coordinates; + } + /** + * + * Adds a coordenate to the array + * @param float | numeric string $latitude + * @param float | numeric string $longitude + * @param float | numeric string $elevation + */ + public function addCoordenate( $latitude, $longitude, $elevation ){ + $this->coordinates[] = $longitude.','.$latitude.','.$elevation; + } + /** + * + * Adds array of coordenates + * @param array $coords + * @throws CException + */ + public function addCoordenates( $coords ){ + if(!is_array( $coords) ) + throw new CException( Yii::t('EGMap','Coordinates parameter must be of type array and are required')); + foreach($coords as $coord){ + $this->coordinates[] = $coord; + } + } + /** + * (non-PHPdoc) + * @see EGMapKMLNode::toXML() + */ + public function toXML(){ + $this->addChild(new EGMapKMLNode('altitudeMode','relative')); + $this->addChild( new EGMapKMLNode('coordinates', $this->coordinates) ); + return parent::toXML(); + } + +}
\ No newline at end of file diff --git a/protected/extensions/egmap/kml/EGMapKMLLineStyle.php b/protected/extensions/egmap/kml/EGMapKMLLineStyle.php new file mode 100644 index 0000000..3a6eae6 --- /dev/null +++ b/protected/extensions/egmap/kml/EGMapKMLLineStyle.php @@ -0,0 +1,86 @@ +<?php +/** + * + * EGMapKMLLineStyle Class + * + * KML LineStyle tag object + * + * @author Antonio Ramirez Cobos + * @link www.ramirezcobos.com + * + * + * @copyright + * + * Copyright (c) 2010 Antonio Ramirez Cobos + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +class EGMapKMLLineStyle extends EGMapKMLNode{ + /** + * + * Style id + * @var string + */ + public $id; + /** + * + * Color node + * Color and opacity (alpha) values are expressed in hexadecimal notation. + * The range of values for any one color is 0 to 255 (00 to ff). For alpha, 00 is fully transparent and ff is fully opaque. + * The order of expression is aabbggrr, where aa=alpha (00 to ff); bb=blue (00 to ff); gg=green (00 to ff); rr=red (00 to ff). + * For example, if you want to apply a blue color with 50 percent opacity to an overlay, you would specify the following: <color>7fff0000</color>, + * where alpha=0x7f, blue=0xff, green=0x00, and red=0x00. + * + * @var string color + */ + public $color; + /** + * + * Width of the line, in pixels. + * @var numeric string + */ + public $width; + /** + * + * Class constructor + * @param string $id + * @param string $lineId + * @param string $color + * @param string $width + */ + public function __construct($id, $lineId = null, $color = null, $width = null){ + + $this->tag = 'LineStyle'; + $this->id = $id; + $this->tagId = $lineId; + $this->color = $color; + $this->width = $width; + } + /** + * (non-PHPdoc) + * @see EGMapKMLNode::toXML() + */ + public function toXML(){ + + $this->checkNode( 'color' ); + $this->checkNode( 'width' ); + + $result = CHtml::openTag( 'Style', array( 'id'=>$this->id ) ); + $result .= parent::toXML(); + $result .= CHtml::closeTag('Style'); + + return $result; + } +}
\ No newline at end of file diff --git a/protected/extensions/egmap/kml/EGMapKMLNode.php b/protected/extensions/egmap/kml/EGMapKMLNode.php new file mode 100644 index 0000000..1013ff5 --- /dev/null +++ b/protected/extensions/egmap/kml/EGMapKMLNode.php @@ -0,0 +1,139 @@ +<?php +/** + * + * EGMapKMLNode Class + * + * KML node base class + * + * @author Antonio Ramirez Cobos + * @link www.ramirezcobos.com + * + * + * @copyright + * + * Copyright (c) 2010 Antonio Ramirez Cobos + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +class EGMapKMLNode { + /** + * + * Tag name + * @var string + */ + public $tag; + /** + * + * Tag id + * @var string + */ + public $tagId; + /** + * + * Tag content + * @var string + */ + public $content; + /** + * + * Tag attributes + * @var array + */ + public $attributes = array(); + /** + * + * Child nodes collection + * @var array $nodes + */ + protected $nodes = array(); // children + /** + * + * Class constructor + * @param string $tag name + * @param string $content + */ + public function __construct($tag, $content = null){ + $this->tag = $tag; + $this->content = $content; + } + /** + * + * Adds a child node to the tag + * @param EGMapKMLNode $node + */ + public function addChild( EGMapKMLNode $node ){ + $this->nodes[] = $node; + } + /** + * + * Clears all added children + */ + public function clearChildren(){ + $this->nodes = array(); + } + /** + * + * @return well formatted XML KML tags + */ + public function toXML(){ + $result = ''; + + if (is_array($this->attributes)) + $this->attributes['id'] = $this->tagId; + else $this->attributes = array(); + + $result .= CHtml::openTag($this->tag, (is_array($this->attributes)? $this->attributes:array())); + if(null !== $this->content && !empty($this->content)) + { + if($this->tag === 'description'){ + $result .= '<![CDATA['. $this->content.']]>'; + } + else if(is_array($this->content)){ + // arrays are separated by carriage return + // they can also be separated by spaces + $result .= implode(PHP_EOL, $this->content); + } + else + $result .= $this->content; + } + $result .= $this->renderChildren(); + $result .= CHtml::closeTag($this->tag); + + return $result; + } + /** + * + * Renders children tags + */ + protected function renderChildren() + { + $children = ''; + if( isset($this->nodes) && is_array($this->nodes) ){ + foreach( $this->nodes as $node ) + $children .= $node->toXML(); + } + return $children; + } + /** + * + * Checks if a node name property has null value + * if not then create a node + * @param string $node + */ + protected function checkNode( $node ){ + if(!is_null($this->$node)) + $this->nodes[] = new EGMapKMLNode($node, $this->$node); + } +}
\ No newline at end of file diff --git a/protected/extensions/egmap/kml/EGMapKMLPlacemark.php b/protected/extensions/egmap/kml/EGMapKMLPlacemark.php new file mode 100644 index 0000000..300df14 --- /dev/null +++ b/protected/extensions/egmap/kml/EGMapKMLPlacemark.php @@ -0,0 +1,76 @@ +<?php +/** + * + * EGMapKMLPlacemark Class + * + * KML Placemark tag object + * + * @author Antonio Ramirez Cobos + * @link www.ramirezcobos.com + * + * + * @copyright + * + * Copyright (c) 2010 Antonio Ramirez Cobos + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +class EGMapKMLPlacemark extends EGMapKMLNode { + /** + * + * Name node + * @var string + */ + public $name; + /** + * + * Description node contents + * @var string + */ + public $description; + /** + * + * styleUrl link (ie #styleID) content + * @var unknown_type + */ + public $styleUrl; + /** + * + * Class constructor + * @param string $name + * @param string $description + * @param string $styleUrl + * @param string $nodes + */ + public function __construct( $name, $description = null, $styleUrl = null, $nodes = array() ){ + $this->tag = 'Placemark'; + $this->name = $name; + $this->description = $description; + $this->styleUrl = $styleUrl; + $this->nodes = is_array($nodes)?$nodes:array(); + } + /** + * (non-PHPdoc) + * @see EGMapKMLNode::toXML() + */ + public function toXML(){ + + $this->checkNode( 'name' ); + $this->checkNode( 'description' ); + $this->checkNode( 'styleUrl' ); + + return parent::toXML(); + } +}
\ No newline at end of file diff --git a/protected/extensions/egmap/kml/EGMapKMLPoint.php b/protected/extensions/egmap/kml/EGMapKMLPoint.php new file mode 100644 index 0000000..5212f4d --- /dev/null +++ b/protected/extensions/egmap/kml/EGMapKMLPoint.php @@ -0,0 +1,95 @@ +<?php +/** + * + * EGMapKMLPoint Class + * + * KML Point tag object + * + * A geographic location defined by longitude, latitude, and (optional) altitude. + * When a Point is contained by a Placemark, the point itself determines the position + * of the Placemark's name and icon. When a Point is extruded, it is connected to the + * ground with a line. This "tether" uses the current LineStyle. + * + * @author Antonio Ramirez Cobos + * @link www.ramirezcobos.com + * + * + * @copyright + * + * Copyright (c) 2010 Antonio Ramirez Cobos + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +class EGMapKMLPoint extends EGMapKMLNode{ + /** + * + * Latitude coord + * @var string + */ + public $latitude; + /** + * + * Longitude coord + * @var string + */ + public $longitude; + /** + * + * Elevation + * @var unknown_type + */ + public $elevation; + /** + * + * Boolean value. Specifies whether to connect the point to the ground with a line. To extrude a Point, + * the value for <altitudeMode> must be either relativeToGround, relativeToSeaFloor, or absolute. + * The point is extruded toward the center of the Earth's sphere. + * Enter description here ... + * @var boolean + */ + public $extrude; + /** + * + * Enter description here ... + * @param string $latitude + * @param string $longitude + * @param string $elevation + */ + public function __construct($latitude, $longitude, $elevation = 0){ + $this->tag = 'Point'; + $this->latitude = $latitude; + $this->longitude = $longitude; + $this->elevation = $elevation; + } + /** + * (non-PHPdoc) + * @see EGMapKMLNode::toXML() + */ + public function toXML(){ + $this->checkNode('extrude'); + /** + * coordinate + * A single tuple consisting of floating point values for longitude, latitude, and altitude (in that order). + * Longitude and latitude values are in degrees + * altitude values (optional) are in meters above sea level + * Do not include spaces between the three values that describe a coordinate. + */ + if(!is_null($this->latitude) && !is_null($this->longitude)) + $this->addChild(new EGMapKMLNode('coordinates', $this->longitude.','.$this->latitude.','.$this->elevation)); + + + return parent::toXML(); + } +}
\ No newline at end of file diff --git a/protected/extensions/egmap/kml/EGMapKMLPolyStyle.php b/protected/extensions/egmap/kml/EGMapKMLPolyStyle.php new file mode 100644 index 0000000..63d4f0f --- /dev/null +++ b/protected/extensions/egmap/kml/EGMapKMLPolyStyle.php @@ -0,0 +1,61 @@ +<?php +/** + * + * EGMapKMLPolyStyle Class + * + * KML PolyStyle tag object + * + * @see EGMapKMLStyle + * + * @author Antonio Ramirez Cobos + * @link www.ramirezcobos.com + * + * + * @copyright + * + * Copyright (c) 2010 Antonio Ramirez Cobos + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +class EGMapKMLPolyStyle extends EGMapKMLLineStyle { + /** + * + * Values for <colorMode> are normal (no effect) and random. A value of random applies a random linear scale to the base <color> as follows. + * To achieve a truly random selection of colors, specify a base <color> of white (ffffffff). + * If you specify a single color component (for example, a value of ff0000ff for red), + * random color values for that one component (red) will be selected. In this case, + * the values would range from 00 (black) to ff (full red). If you specify values for two or + * for all three color components, a random linear scale is applied to each color component, + * with results ranging from black to the maximum values specified for each component. + * The opacity of a color comes from the alpha component of <color> and is never randomized. + * @var string color Mode + */ + public $colorMode; + /** + * + * Class Constructor + * @param string $id + * @param string $polyId + * @param string $color + * @param string $colorMode + */ + public function __construct($id, $polyId = null, $color = null, $colorMode = null){ + $this->tag = 'PolyStyle'; + $this->id = $id; + $this->tagId = $polyId; + $this->color = $color; + $this->colorMode = $colorMode; + } +}
\ No newline at end of file diff --git a/protected/extensions/egmap/kml/EGMapKMLPolygon.php b/protected/extensions/egmap/kml/EGMapKMLPolygon.php new file mode 100644 index 0000000..230dbb5 --- /dev/null +++ b/protected/extensions/egmap/kml/EGMapKMLPolygon.php @@ -0,0 +1,131 @@ +<?php +/** + * + * EGMapKMLPolygon Class + * + * KML Polygon tag object + * + * A Polygon is defined by an outer boundary and 0 or more inner boundaries. The boundaries, in turn, are defined + * by LinearRings. When a Polygon is extruded, its boundaries are connected to the ground to form additional polygons, + * which gives the appearance of a building or a box. Extruded Polygons use <PolyStyle> for their color, color mode, and fill. + * The <coordinates> for polygons must be specified in counterclockwise order. Polygons follow the "right-hand rule," + * which states that if you place the fingers of your right hand in the direction in which the coordinates are specified, + * your thumb points in the general direction of the geometric normal for the polygon. + * + * + * @author Antonio Ramirez Cobos + * @link www.ramirezcobos.com + * + * + * @copyright + * + * Copyright (c) 2010 Antonio Ramirez Cobos + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +class EGMapKMLPolygon extends EGMapKMLNode{ + /** + * <Polygon> + * <innerBoundaryIs> // only supported here + * <LinearRing> + * <coordinates> + * -122.366212,37.818977,30 + * -122.365424,37.819294,30 + * </coordinates> + * </LinearRing> + * </innerBoundaryIs> + * </Polygon> + * Another way + * <MultiGeometry> + * <Polygon> + * <outerBoundaryIs> + * <LinearRing> + * <coordinates>-122.1,37.4,0 -122.0,37.4,0 -122.0,37.5,0 -122.1,37.5,0 -122.1,37.4,0</coordinates> + * </LinearRing> + * </outerBoundaryIs> + * </Polygon> + * </MultiGeometry> + * + * <outerBoundaryIs> (required) + * Contains a <LinearRing> element. + * <innerBoundaryIs> + * Contains a <LinearRing> element. + * A Polygon can contain multiple <innerBoundaryIs> elements, + * which create multiple cut-outs inside the Polygon. + */ + /** + * + * Coordinates array + * @var array + */ + protected $coordinates = array(); + /** + * + * outerBoundaryIs = true + * innerBoundaryIs = false + * @var boolean + */ + protected $boundary; + + /** + * + * Enter description here ... + * @param boolean $outerBoundaryIs + * @param array $coordinates + */ + public function __construct( $outerBoundaryIs = false, $coordinates = array() ){ + + $this->tag = 'Polygon'; + $this->boundary = $outerBoundaryIs; + if(is_array($coordinates)) $this->coordinates = $coordinates; + } + /** + * + * Adds a coordenate to the array + * @param float | numeric string $latitude + * @param float | numeric string $longitude + * @param float | numeric string $elevation + */ + public function addCoordenate( $latitude, $longitude, $elevation ){ + $this->coordinates[] = $longitude.','.$latitude.','.$elevation; + } + /** + * + * Adds array of coordenates + * @param array $coords + * @throws CException + */ + public function addCoordenates( $coords ){ + if(!is_array( $coords) ) + throw new CException( Yii::t('EGMap','Coordinates parameter must be of type array')); + foreach($coords as $coord){ + $this->coordinates[] = $coord; + } + } + /** + * (non-PHPdoc) + * @see EGMapKMLNode::toXML() + */ + public function toXML(){ + $node = new EGMapKMLNode('LinearRing'); + $node->addChild(new EGMapKMLNode('coordinates', $this->coordinates )); + $parentNode = new EGMapKMLNode(($this->boundary?'outerBoundaryIs':'innerBoundaryIs')); + $parentNode->addChild( $node ); + $this->addChild( $parentNode ); + + return parent::toXML(); + } + +}
\ No newline at end of file |
