Yii 2.0: Simple Google Maps object for use with ajax maps

3 followers

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

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

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!

Total 1 comment

#19642 report it
carlo_ab at 2015/10/27 01:03pm
Error

Hi Chris,

I get the following error:

Undefined variable: js

Thank you very much.

Carlo

Leave a comment

Please to leave your comment.

Write new article