The Google mapping extension by Dos Amigos (link) is really great but there are difficulties with Google maps when you want to manipulate your map object with Ajax.
Thanks to some core code from Dos Amigos, I have fashioned a simpler way to manage ajax manipulation of Google maps.
The method described here enables you to create a map canvas and then update it over time with Ajax calls.
First, create a javascript file with the following code
[javascript]
var myGMap = (function(){
var gmap0infoWindow;
var gmap0;
var gmarker = [];
var container;
var mapOptions;
function myGMap(){
this.canvas = 'gmap0-map-canvas';
this.lat = 43.7621527000;
this.long = 2.9246927000;
this.zoom = 7;
for(var prop in arguments[0]) {
if(this.hasOwnProperty(prop)) {
this[prop]=arguments[0][prop];
}
}
mapOptions = {"center":new google.maps.LatLng( this.lat, this.long ),"zoom": this.zoom};
console.log('set map canvas:' + this.canvas);
console.log(this);
container = document.getElementById( this.canvas );
if (container)
{
container.style.width = '100%';
container.style.height = '512px';
gmap0 = new google.maps.Map(container, mapOptions);
gmap0infoWindow = new google.maps.InfoWindow();
}
// google.maps.event.addDomListener(window, 'load', initialize);
}
myGMap.prototype.getMap = function() {
return gmap0;
}
myGMap.prototype.addMarker = function(lat, lng, title, content, iconFile) {
count = gmarker.length;
gmarker[count] = new google.maps.Marker({
"map": gmap0,
"position": new google.maps.LatLng(lat, lng),
"title": title,
"icon": iconFile
});
google.maps.event.addListener(gmarker[count], 'click', function(event){
gmap0infoWindow.setContent( content );
gmap0infoWindow.open(gmap0, this);
});
}
myGMap.prototype.clearMarkers = function() {
for (var i = 0; i < gmarker.length; i++) {
gmarker[i].setMap( null );
}
gmarker = [];
}
return myGMap;
})();
and then include it in your view, probably using an asset file.
Somewhere in a view, render the map canvas, something like this
<div class="col-md-12">
<div id="gmap0-map-canvas"></div>
</div>
Now, you have the choice of initialising the map at the bottom of the same view
$js .= "gmap0 = new myGMap({canvas: 'gmap0-map-canvas'}); ";
// options include {
// canvas: "element id of canvas" - defaults to gmap0-map-canvas
// lat: latitude of center of map,
// long: longitude of center of map,
// zoom: zoom factor
// }
$this->registerJs($js, View::POS_READY, 'map_tab');
and then adding map Markers
$js .= "gmap0.addMarker( 43.308941, 3.346367, 'html for popup box', '/path/to/custom_icon.png');
or, in a more complex scenario, you can return the addMarkers in an Ajax call
[javascript]
link = 'url/to/action-that-returns-just-javascript';
gmap0.clearMarkers();
$.getScript( link , function( data, textStatus, jqxhr ) {
// refresh map to get it to display new markers
// you can also use this. if you need to refresh the map eg: when changing tabs
setTimeout(function() {map = gmap0.getMap(); var center = map.getCenter(); google.maps.event.trigger(map, 'resize'); map.setCenter(center);}, 500);
});
example of action-that-returns-just-javascript
public function actionThatReturnsJustJavascript()
{
$markers = SomeModel::find()->where(some condition)->all();
foreach($markers as $marker) {
echo $marker->mapMarker('gmap0');
}
}
// marker model
public function getMapMarker($gmapId)
{
$js = $mapId.".addMarker( $this->lat, $this->lng, '{$this->title}', '$this->content', '/images/icons/$this->type.png');";
return $js;
}
As the map canvas name is configurable, you can easily include more than one map on a page, without any conflicts between the multiple maps. This would also apply to having one map in your main page and then others in pop-ups or overlays.
Happy mapping!
Error
Hi Chris,
I get the following error:
Undefined variable: js
Thank you very much.
Carlo
If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.