Search code examples
jquerygoogle-mapsgoogle-maps-api-3expressionengineinfowindow

How to create custom google maps (api v3) marker info windows (within context of a specific example)


1) So there's this great example of showing groups of markers by clicking on checkboxes, and I'd like to extend this by customizing the marker infowindow. Below is the code from this example - it works great for toggling markers, but has unstyled infowindows. I've made some additional customizations to it already. Namely, stylized the map and added responsiveness so that the markers stay centered when the browser window is changed:

//<![CDATA[
  // this variable will collect the html which will eventually be placed in the side_bar 
  var side_bar_html = ""; 

  var gmarkers = [];
  var gicons = [];
  var map = null;

 var infowindow = new google.maps.InfoWindow(
 { 
   size: new google.maps.Size(150,50)
  });

gicons["red"] = new google.maps.MarkerImage("mapIcons/marker_red.png",
  // This marker is 20 pixels wide by 34 pixels tall.
  new google.maps.Size(20, 34),
  // The origin for this image is 0,0.
  new google.maps.Point(0,0),
  // The anchor for this image is at 9,34.
   new google.maps.Point(9, 34));
// Marker sizes are expressed as a Size of X,Y
// where the origin of the image (0,0) is located
// in the top left of the image.

// Origins, anchor positions and coordinates of the marker
// increase in the X direction to the right and in
// the Y direction down.

var iconImage = new google.maps.MarkerImage('mapIcons/marker_red.png',
  // This marker is 20 pixels wide by 34 pixels tall.
  new google.maps.Size(20, 34),
  // The origin for this image is 0,0.
  new google.maps.Point(0,0),
  // The anchor for this image is at 9,34.
  new google.maps.Point(9, 34));
var iconShadow = new google.maps.MarkerImage('http://www.google.com/mapfiles/shadow50.png',
  // The shadow image is larger in the horizontal dimension
  // while the position and offset are the same as for the main image.
  new google.maps.Size(37, 34),
  new google.maps.Point(0,0),
  new google.maps.Point(9, 34));
  // Shapes define the clickable region of the icon.
  // The type defines an HTML &lt;area&gt; element 'poly' which
  // traces out a polygon as a series of X,Y points. The final
  // coordinate closes the poly by connecting to the first
  // coordinate.
var iconShape = {
  coord:  [9,0,6,1,4,2,2,4,0,8,0,12,1,14,2,16,5,19,7,23,8,26,9,30,9,34,11,34,11,30,12,26,13,24,14,21,16,18,18,16,20,12,20,8,18,4,16,2,15,1,13,0],
  type: 'poly'
};

function getMarkerImage(iconColor) {
   if ((typeof(iconColor)=="undefined") || (iconColor==null)) { 
  iconColor = "red"; 
}
if (!gicons[iconColor]) {
  gicons[iconColor] = new google.maps.MarkerImage("mapIcons/marker_"+ iconColor +".png",
  // This marker is 20 pixels wide by 34 pixels tall.
  new google.maps.Size(20, 34),
  // The origin for this image is 0,0.
  new google.maps.Point(0,0),
  // The anchor for this image is at 6,20.
  new google.maps.Point(9, 34));
 } 
 return gicons[iconColor];

 }

function category2color(category) {
   var color = "red";
   switch(category) {
     case "theatre": color = "blue";
            break;
     case "golf":    color = "green";
            break;
     case "info":    color = "yellow";
                break;
 default:   color = "red";
            break;
   }
   return color;
}

  gicons["theatre"] = getMarkerImage(category2color("theatre"));
  gicons["golf"] = getMarkerImage(category2color("golf"));
  gicons["info"] = getMarkerImage(category2color("info"));

  // A function to create the marker and set up the event window
function createMarker(latlng,name,html,category) {
var contentString = html;
var marker = new google.maps.Marker({
    position: latlng,
    icon: gicons[category],
    shadow: iconShadow,
    map: map,
    title: name,
    zIndex: Math.round(latlng.lat()*-100000)<<5
    });
    // === Store the category and name info as a marker properties ===
    marker.mycategory = category;                                 
    marker.myname = name;
    gmarkers.push(marker);

 google.maps.event.addListener(marker, 'click', function() {
    infowindow.setContent(contentString); 
    infowindow.open(map,marker);
    });
 }

  // == shows all markers of a particular category, and ensures the checkbox is checked ==
  function show(category) {
    for (var i=0; i<gmarkers.length; i++) {
      if (gmarkers[i].mycategory == category) {
        gmarkers[i].setVisible(true);
      }
    }
    // == check the checkbox ==
    document.getElementById(category+"box").checked = true;
  }

  // == hides all markers of a particular category, and ensures the checkbox is cleared ==
  function hide(category) {
    for (var i=0; i<gmarkers.length; i++) {
      if (gmarkers[i].mycategory == category) {
        gmarkers[i].setVisible(false);
      }
    }
    // == clear the checkbox ==
    document.getElementById(category+"box").checked = false;
    // == close the info window, in case its open on a marker that we just hid
    infowindow.close();
  }

  // == a checkbox has been clicked ==
  function boxclick(box,category) {
    if (box.checked) {
      show(category);
    } else {
      hide(category);
    }
    // == rebuild the side bar
    makeSidebar();
  }

  function myclick(i) {
    google.maps.event.trigger(gmarkers[i],"click");
  }


  // == rebuilds the sidebar to match the markers currently displayed ==
  function makeSidebar() {
    var html = "";
    for (var i=0; i<gmarkers.length; i++) {
      if (gmarkers[i].getVisible()) {
        html += '<a href="javascript:myclick(' + i + ')">' + gmarkers[i].myname + '<\/a><br>';
      }
    }
    document.getElementById("side_bar").innerHTML = html;
  }

function initialize() {

var styles = [
{
"featureType": "landscape.natural",
"elementType": "geometry.fill",
"stylers": [
  { "color": "#d5d0c8" }
]
},{
"featureType": "water",
"stylers": [
  { "invert_lightness": true },
  { "visibility": "simplified" }
]
},{
"featureType": "road.local",
"elementType": "geometry.fill",
"stylers": [
  { "color": "#c4bfb5" },
  { "visibility": "on" }
]
},{
"featureType": "road.arterial",
"elementType": "geometry",
"stylers": [
  { "color": "#ffffff" },
  { "visibility": "simplified" }
]
},{
"featureType": "road.local",
"elementType": "labels.text.stroke",
"stylers": [
  { "color": "#c4bfb5" }
]
},{
"featureType": "road.local",
"elementType": "labels.text.fill",
"stylers": [
  { "color": "#ffffff" }
]
},{
"featureType": "road.highway",
"elementType": "geometry",
"stylers": [
  { "color": "#ffffff" },
  { "visibility": "on" }
]
},{
"featureType": "road.highway",
"elementType": "labels.text.stroke",
"stylers": [
  { "color": "#ffffff" }
]
},{
"featureType": "road.arterial",
"elementType": "labels.text.stroke",
"stylers": [
  { "color": "#ffffff" }
]
},{
"featureType": "landscape.natural.terrain",
"elementType": "geometry",
"stylers": [
  { "color": "#c9c4b4" }
]
},{
"featureType": "poi.park",
"elementType": "labels.text.stroke",
"stylers": [
  { "color": "#808080" },
  { "visibility": "off" }
]
},{
"featureType": "landscape.man_made",
"stylers": [
  { "visibility": "off" }
]
}
];

// Create a new StyledMapType object, passing it the array of styles,
// as well as the name to be displayed on the map type control.
var styledMap = new google.maps.StyledMapType(styles,
 {name: "Styled Map"});


var myOptions = {
  zoom: 11,
  center: new google.maps.LatLng(53.8363,-3.0377),
  mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById("map"), myOptions);


google.maps.event.addListener(map, 'click', function() {
    infowindow.close();
    });


// Ensure the map stays centered when we resize the browser
google.maps.event.addDomListener(window, "resize", function() {
    var center = map.getCenter();
    google.maps.event.trigger(map, "resize");
    map.setCenter(center); 
});    

//Associate the styled map with the MapTypeId and set it to display.
map.mapTypes.set('map_style', styledMap);
map.setMapTypeId('map_style');

  // Read the data
  downloadUrl("categories.xml", function(doc) {
var xml = xmlParse(doc);
var markers = xml.documentElement.getElementsByTagName("marker");

    for (var i = 0; i < markers.length; i++) {
      // obtain the attribues of each marker
      var lat = parseFloat(markers[i].getAttribute("lat"));
      var lng = parseFloat(markers[i].getAttribute("lng"));
      var point = new google.maps.LatLng(lat,lng);
      var address = markers[i].getAttribute("address");
      var name = markers[i].getAttribute("name");
      var html = "<b>"+name+"<\/b><p>"+address;
      var category = markers[i].getAttribute("category");
      // create the marker
      var marker = createMarker(point,name,html,category);
    }

    // == show or hide the categories initially ==
    show("theatre");
    hide("golf");
    hide("info");
    // == create the initial sidebar ==
    makeSidebar();
  });
}

// This Javascript is based on code provided by the
// Community Church Javascript Team
// http://www.bisphamchurch.org.uk/   
// http://econym.org.uk/gmap/
// from the v2 tutorial page at:
// http://econym.org.uk/gmap/example_categories.htm
//]]>

And here is the categories.xml content:

<markers>
      <marker name="Grand Theatre" address="33 Church St, Blackpool, Lancashire, FY1 1HT" lng="-3.053102" lat="53.817260" category="theatre" />
      <marker name="Claremont Theatre Club" address="Burwood Dr, Blackpool, Lancashire, FY3 8NS" lng="-3.049690" lat="53.829649" category="theatre" />
       ETC...
</markers>

2) I found the following working example of really nice, styled infowindows over here. I just don't know how to use that code with the js code above. Here is the resulting javascript from this particular example. If there's a better way to do it, and it works with the code with #1 above I am fully open to that. No ties to the ExpressionEngine CMS method that this example uses.

var options = {
        alignBottom: true,
        boxClass: "ui-infobox-dark",
        boxStyle: {width:'250px'},
                closeBoxMargin: "",
                closeBoxURL: "white-close-button.png",
                disableAutoPan: false,
                enableEventPropagation: false,
                infoBoxClearance: new google.maps.Size(0, 0),
                isHidden: false,
                maxWidth: 0,
                pane: "floatPane",
                pixelOffset: new google.maps.Size(0, 0),
                zIndex: null
            };

            var infowindow  = new InfoBox(options);

            var obj = map7_markers[index];      


            map7_windows.push(infowindow);

            google.maps.event.addListener(obj, 'click', function(e) {
                obj.position = e.latLng;                            
                obj.getPosition = function() {
                    return e.latLng;
                }                   
                    for(var i = 0; i < map7_windows.length; i++) {
                        map7_windows[i].close();
                    }
                infowindow.setPosition(e.latLng);
                infowindow.open(map7_map, obj);

            });

            map7_window = infowindow;

Solution

  • You can checkout a working example here. http://vibe9design.com/seylynn_map/