Related
The code may seem idiotic. This is my first try at using knockout.
I am working on a neighborhood map. The task is to invoke an event when any item on the list is clicked. The event is, when the item(place title) is clicked, the respective marker shows a infoWindow. I tried to implement it and ended up using google API function. Its not happening. I need a way solve this and make it happen.
HTML
<div>
<h1>Famous places in Bhubaneswar</h1>
<section class="main">
<form class="search" method="post" action="index.html" >
<input type="text" data-bind="textInput: filter" placeholder="Click here/Type the name of the place">
<ul style="list-style-type: none;" data-bind="foreach: filteredItems">
<li>
<span data-bind="text: title, click: $parent.showInfoWindow"></span>
</li>
</ul>
</form>
</section>
<div id="map"></div>
</div>
JS
var map;
var locations = [
{
title: 'Lingaraj Temple',
location:
{
lat: 20.2382383,
lng: 85.8315622
}
},
{
title: 'Odisha State Museum',
location:
{
lat: 20.2562,
lng: 85.8415
}
},
{
title: 'Dhauli',
location:
{
lat: 20.1923517,
lng: 85.8372062
}
},
{
title: 'Nandankanan Zoological Park',
location:
{
lat: 20.395775,
lng: 85.8237923
}
},
{
title: 'Udayagiri Caves',
location:
{
lat: 20.2631,
lng: 85.7857
}
},
{
title: 'Kalinga Stadium',
location:
{
lat: 20.2879847,
lng: 85.8215891
}
}
];
var center =[{lat : 20.2961, lng : 85.8245}]
var markers = []; // Creating a new blank array for all the listing markers.
var styles = [
{
featureType: 'water',
stylers: [
{ color: '#19a0d8' }
]
},
{
featureType: 'administrative',
elementType: 'labels.text.stroke',
stylers: [
{ color: '#ffffff' },
{ weight: 6 }
]
},
{
featureType: 'administrative',
elementType: 'labels.text.fill',
stylers: [
{ color: '#e85113' }
]
},
{
featureType: 'road.highway',
elementType: 'geometry.stroke',
stylers: [
{ color: '#efe9e4' },
{ lightness: -40 }
]
},
{
featureType: 'transit.station',
stylers: [
{ weight: 9 },
{ hue: '#e85113' }
]
},
{
featureType: 'road.highway',
elementType: 'labels.icon',
stylers: [
{ visibility: 'off' }
]
},
{
featureType: 'water',
elementType: 'labels.text.stroke',
stylers: [
{ lightness: 100 }
]
},
{
featureType: 'water',
elementType: 'labels.text.fill',
stylers: [
{ lightness: -100 }
]
},
{
featureType: 'poi',
elementType: 'geometry',
stylers: [
{ visibility: 'on' },
{ color: '#f0e4d3' }
]
},
{
featureType: 'road.highway',
elementType: 'geometry.fill',
stylers: [
{ color: '#efe9e4' },
{ lightness: -25 }
]
}
];
function initMap() {
// Constructor creates a new map
map = new google.maps.Map(document.getElementById('map'), {
center: center[0],
zoom: 13,
styles: styles,
mapTypeControl: false
});
var largeInfowindow = new google.maps.InfoWindow();
var bounds = new google.maps.LatLngBounds();
var defaultIcon = makeMarkerIcon('0091ff'); // this is the default marker icon.
var highlightedIcon = makeMarkerIcon('FFFF24'); // this is the state of the marker when highlighted.
for (var i = 0; i < locations.length; i++) {
var position = locations[i].location; // Get the position from the location array.
var title = locations[i].title;
// var locationUrl = wikiLink(locations[i]);
// console.log(locationUrl);
wikiLink(locations[i]);
// Create a marker per location, and put into markers array.
var marker = new google.maps.Marker({
map: map,
position: position,
title: title,
animation: google.maps.Animation.DROP,
id: i,
// url: locationUrl
});
markers.push(marker); // Push the marker to our array of markers.
// Create an onclick event to open an infowindow at each marker.
marker.addListener('click', function() {
populateInfoWindow(this, largeInfowindow);
});
bounds.extend(markers[i].position);
marker.addListener('mouseover', function() {
this.setIcon(highlightedIcon);
});
marker.addListener('mouseout', function() {
this.setIcon(defaultIcon);
});
}
// Extend the boundaries of the map for each marker
map.fitBounds(bounds);
function wikiLink(location) {
location.url = '';
var wikiUrl = 'https://en.wikipedia.org/w/api.php?action=opensearch&search=' + title + '&format=json&callback=wikiCallback';
//If you cant get a wiki request, throw an error message.
var wikiError = setTimeout(function() {
location.url = 'Unable to find the request';
}, 8000);
$.ajax({
url: wikiUrl,
dataType: "jsonp",
jsonp: "callback",
success: function(response) {
console.log(response);
var url = response[3][0];
console.log(url);
location.url = url;
console.log(location.url);
clearTimeout(wikiError);
}
});
};
}
// This function populates the infowindow when the marker is clicked. We'll only allow
// one infowindow which will open at the marker that is clicked, and populate based
// on that markers position.
function populateInfoWindow(marker, infowindow) {
// Check to make sure the infowindow is not already opened on this marker.
if (infowindow.marker != marker) {
infowindow.setContent(''); // Clear the infowindow content to give the streetview time to load.
infowindow.marker = marker;
// Make sure the marker property is cleared if the infowindow is closed.
infowindow.addListener('closeclick', function() {
infowindow.marker = null;
});
var streetViewService = new google.maps.StreetViewService();
var radius = 500;
// In case the status is OK, which means the pano was found, compute the
// position of the streetview image, then calculate the heading, then get a
// panorama from that and set the options
function getStreetView(data, status) {
if (status == google.maps.StreetViewStatus.OK) {
var nearStreetViewLocation = data.location.latLng;
var heading = google.maps.geometry.spherical.computeHeading(
nearStreetViewLocation, marker.position);
console.log(marker.position);
infowindow.setContent('<div>' + marker.title + '</div><hr><div id="pano"></div><div><a href=' + location.url + '> Click here for more info </a></div>');
var panoramaOptions = {
position: nearStreetViewLocation,
pov: {
heading: heading,
pitch: 30
}
};
var panorama = new google.maps.StreetViewPanorama(
document.getElementById('pano'), panoramaOptions);
} else {
infowindow.setContent('<div>' + marker.title + '</div><hr>' + '<div>No Street View Found</div>');
}
}
// Use streetview service to get the closest streetview image within 50 meters of the markers position
streetViewService.getPanoramaByLocation(marker.position, radius, getStreetView);
infowindow.open(map, marker); // Open the infowindow on the correct marker.
}
}
// This function takes in a COLOR, and then creates a new marker icon of that color.
// The icon will be 21 px wide by 34 high, have an origin of 0, 0 and be anchored at 10, 34).
function makeMarkerIcon(markerColor) {
var markerImage = new google.maps.MarkerImage(
'http://chart.googleapis.com/chart?chst=d_map_spin&chld=1.15|0|'+ markerColor +
'|40|_|%E2%80%A2',
new google.maps.Size(21, 34),
new google.maps.Point(0, 0),
new google.maps.Point(10, 34),
new google.maps.Size(21,34));
return markerImage;
}
function viewModel(markers) {
var self = this;
self.filter = ko.observable(''); // this is for the search box, takes value in it and searches for it in the array
self.items = ko.observableArray(locations); // we have made the array of locations into a ko.observableArray
// attributed to - http://www.knockmeout.net/2011/04/utility-functions-in-knockoutjs.html , filtering through array
self.filteredItems = ko.computed(function() {
var filter = self.filter().toLowerCase();
if (!filter) {
return self.items();
} else {
return ko.utils.arrayFilter(self.items(), function(id) {
console.log(id.title);
return stringStartsWith(id.title.toLowerCase(), filter);
});
}
});
var stringStartsWith = function (string, startsWith) {
string = string || "";
if (startsWith.length > string.length)
return false;
return string.substring(0, startsWith.length) === startsWith;
};
// populateInfoWindow(self.filteredItems,)
this.listInfoWindow = new google.maps.InfoWindow();
for (var i = 0; i < markers.length; i++) {
var marker = markers[i];
this.showInfoWindow = function(marker) {
marker.addListener('click', function() {
populateInfoWindow(this, largeInfowindow);
});
}
}
// this.showInfoWindow = function(place) { // this should show the infowindow if any place on the list is clicked
// console.log(place.marker);
// google.maps.event.trigger(place.marker, 'click');
// };
}
ko.applyBindings(new viewModel());
You haven't shown it here, but I expect that you're loading the Google Map API asyncronously, and then trying to use that API in your JS/Knockout code before it has finished loading. I did this project, and I had that problem for a bit.
What you need to do is delay your JS code from running until the Google Map API has fully loaded in. You can do that with a callback. You can see it used on this page from the API's docs.
I am creating a Google map with multiple markers that I want to popup into a Fancybox lightbox when clicked on. I must admit, I am quite a novice at javascript and Google Maps API.
I have put some pieces of different sample scripts together and come up with something that actually works decently. I have the markers the way I want them (well, without captions... which I still have to figure out), the style of map the way I want it, and I even have the markers popping up lightboxes when clicked on.
However, all markers end up opening one URL in the lightbox. I guess that makes a bit of sense. The Fancybox code is being distributed to all the markers, instead of each one individually. I tried to make another argument with a url and pass it into the Fancybox script, but it still just picks up the last marker's url and uses it for all the markers. How would I be able to get the URL to work for each marker instead of all the markers at once?
I did find a similar question on here:
Multiple fancybox google map
However, it seams to use a different route of attacking the same issue. Plus, I can't seem to get their script to work by itself, let alone integrate it with my code. So, while I get how the solution works for them, it doesn't seem to help me.
My code is as follows:
var map;
var MY_MAPTYPE_ID = 'custom_style';
function initialize() {
var featureOpts = [
{
stylers: [
{ hue: '#CCCCCC' },
{ saturation: '-100' },
{ visibility: 'simplified' },
{ gamma: 2 },
{ weight: .4 }
]
},
{
elementType: 'labels',
stylers: [
{ visibility: 'off' }
]
},
{
featureType: 'water',
stylers: [
{ color: '#efefef' }
]
}
];
var mapOptions = {
zoom: 9,
scrollwheel: false,
keyboardShortcuts: false,
disableDefaultUI: true,
center: new google.maps.LatLng(34.0531553, -84.3615928),
mapTypeControlOptions: {
mapTypeIds: [google.maps.MapTypeId.ROADMAP, MY_MAPTYPE_ID]
},
mapTypeId: MY_MAPTYPE_ID
};
map = new google.maps.Map(document.getElementById('map-canvas'),
mapOptions);
var styledMapOptions = {
name: 'Custom Style'
};
var customMapType = new google.maps.StyledMapType(featureOpts, styledMapOptions);
map.mapTypes.set(MY_MAPTYPE_ID, customMapType);
setMarkers(map, schools);
}
var schools = [
['Canton', 34.2352063, -84.4846274, 4, 'popup.htm'],
['Austell', 33.8158106, -84.6334938999999, 3, 'popup.htm'],
['Marietta', 33.9578674, -84.5532791, 2, 'popup.htm'],
['Atlanta', 33.7635085, -84.43030209999999, 1, 'popup2.htm']
];
function setMarkers(map, locations) {
var image = {
url: 'images/fml-home.png',
size: new google.maps.Size(67, 63),
origin: new google.maps.Point(0,0),
anchor: new google.maps.Point(0, 63)
};
var shadow = {
url: 'images/fml-shadow.png',
size: new google.maps.Size(45, 18),
origin: new google.maps.Point(0,0),
anchor: new google.maps.Point(0, 18)
};
var shape = {
coord: [1, 1, 1, 67, 60, 67, 60 , 1],
type: 'poly'
};
for (var i = 0; i < locations.length; i++) {
var schools = locations[i];
var myLatLng = new google.maps.LatLng(schools[1], schools[2]);
var marker = new google.maps.Marker({
position: myLatLng,
map: map,
shadow: shadow,
icon: image,
shape: shape,
title: schools[0],
zIndex: schools[3]
});
var href = schools[4];
google.maps.event.addListener(marker, 'click', function() {
$.fancybox({
frameWidth : 800,
frameHeight : 600,
href : href,
type : 'iframe'
});
});
}
}
google.maps.event.addDomListener(window, 'load', initialize);
Try this:
marker["href"] = schools[4];
google.maps.event.addListener(marker, 'click', function() {
$.fancybox({
frameWidth : 800,
frameHeight : 600,
href : this.href,
type : 'iframe'
});
});
I'd appreciate some help setting up two Google maps (API 3) on a single page. They've got some shared styles. I can get a single one running, but not two together.
http://theredfrog.com/new/temp3.html - one map (ok)
http://theredfrog.com/new/temp4.html - two maps (broken)
Here's the script...
<script type="text/javascript">
function initialize() {
var styles = [
....
];
var hulloptions = {
mapTypeControlOptions: {
mapTypeIds: [ 'Styled']
},
center: new google.maps.LatLng(53.7413176, -0.3353987),
zoom: 15,
mapTypeId: 'StyledHull'
};
var leedsoptions = {
mapTypeControlOptions: {
mapTypeIds: [ 'Styled']
},
center: new google.maps.LatLng(53.796177,-1.541862),
zoom: 15,
mapTypeId: 'StyledLeeds'
};
maphull = new google.maps.Map(document.getElementById("map-hull"),hulloptions);
mapleeds = new google.maps.Map(document.getElementById("map-leeds"),leedsoptions);
var image = './skin/logo.png';
var HullLatLng = new google.maps.LatLng(53.7413176, -0.3353987);
var LeedsLatLng = new google.maps.LatLng(53.796177,-1.541862);
var rfdMarkerHull = new google.maps.Marker({
position: HullLatLng,
map: maphull,
icon: image
});
var rfdMarkerLeeds = new google.maps.Marker({
position: LeedsLatLng,
map: leedshull,
icon: image
});
var styledMapTypeHull = new google.maps.StyledMapTypeHull(styles, { name: 'RFD Hull' });
var styledMapTypeLeeds = new google.maps.StyledMapTypeLeeds(styles, { name: 'RFD Leeds' });
maphull.mapTypes.set('StyledHull', styledMapTypeHull);
mapleeds.mapTypes.set('StyledLeeds', styledMapTypeLeeds);
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
These two lines don't look right:
var styledMapTypeHull = new google.maps.StyledMapTypeHull(styles, { name: 'RFD Hull' });
var styledMapTypeLeeds = new google.maps.StyledMapTypeLeeds(styles, { name: 'RFD Leeds' });
Don't you get an error in the JavaScript console on those?
I think you meant:
var styledMapTypeHull = new google.maps.StyledMapType( styles, {
name: 'RFD Hull'
});
var styledMapTypeLeeds = new google.maps.StyledMapType( styles, {
name: 'RFD Leeds'
});
(also reformatted slightly for shorter lines)
Here's some more information and a working example.
And now that I try your second map in with the Developer Tools open in Chrome, I see there are other errors before it even gets that far.
First a warning:
Warning: you have included the Google Maps API multiple times
on this page. This may cause unexpected errors.
Then lazyload is undefined here in plugins.js:
$(".lazy").lazyload({
effect: "fadeIn",
effectspeed: 600,
failure_limit: 10
});
And then a mysterious-looking error inside some Maps API compressed code, but if you look at the call stack, you'll see your initialize function in the stack, and if you click on that it goes to this line:
mapleeds = new google.maps.Map(document.getElementById("map-leeds"),leedsoptions);
Paste this into the JavaScript console and you'll see what's wrong:
document.getElementById("map-leeds")
And more errors after that, before even getting to the problem I saw while looking at your code.
So you have some debugging to do. Are you familiar with the Developer Tools in Chrome or another browser? If not, now it is time! Here is a great introduction to the Chrome DevTools.
Your problems are (you need to run through your code with a debugger):
typos (map: mapleeds, not map: leedshull,
ordering, you can't use variables before you initialize them
these are not valid: google.maps.StyledMapTypeHull, google.maps.StyledMapTypeLeeds (maybe a search and replace gone wrong. Should be google.maps.StyledMapType
<script type="text/javascript">
var maphull = null;
var mapleeds = null;
function initialize() {
var styles = [
{
stylers: [
{ saturation: -100 }
]
},{
featureType: 'water',
elementType: 'all',
stylers: [
{ lightness: -74 },
{ visibility: 'on' }
]
},{
featureType: 'landscape',
elementType: 'geometry',
stylers: [
{ lightness: -26 },
{ visibility: 'simplified' }
]
},{
featureType: 'road',
elementType: 'geometry',
stylers: [
{ hue: '#efefef' },
{ lightness: 83 },
{ visibility: 'simplified' }
]
},{
featureType: 'poi',
elementType: 'all',
stylers: [
{ hue: '#999999' },
{ saturation: -100 },
{ lightness: -23 },
{ visibility: 'on' }
]
},{
featureType: 'road',
elementType: 'labels',
stylers: [
{ saturation: -100 },
{ visibility: 'on' }
]
}
];
var hulloptions = {
mapTypeControlOptions: {
mapTypeIds: [ 'Styled']
},
center: new google.maps.LatLng(53.7413176, -0.3353987),
zoom: 15,
mapTypeId: 'StyledHull'
};
var leedsoptions = {
mapTypeControlOptions: {
mapTypeIds: [ 'Styled']
},
center: new google.maps.LatLng(53.796177,-1.541862),
zoom: 15,
mapTypeId: 'StyledLeeds'
};
var image = './skin/logo.png';
var HullLatLng = new google.maps.LatLng(53.7413176, -0.3353987);
var LeedsLatLng = new google.maps.LatLng(53.796177,-1.541862);
var styledMapTypeHull = new google.maps.StyledMapType(styles, { name: 'RFD Hull' });
var styledMapTypeLeeds = new google.maps.StyledMapType(styles, { name: 'RFD Leeds' });
maphull = new google.maps.Map(document.getElementById("map-hull"),hulloptions);
mapleeds = new google.maps.Map(document.getElementById("map-leeds"),leedsoptions);
maphull.mapTypes.set('StyledHull', styledMapTypeHull);
mapleeds.mapTypes.set('StyledLeeds', styledMapTypeLeeds);
var rfdMarkerHull = new google.maps.Marker({
position: HullLatLng,
map: maphull,
icon: image
});
var rfdMarkerLeeds = new google.maps.Marker({
position: LeedsLatLng,
map: mapleeds,
icon: image
});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
I'm in the process of creating an interactive campus map using the Google Maps API and KML. I have a map with a Ground Overlay and a layer of KML markers. I am trying to figure out how to get the KML layer to toggle. I currently have it set to toggle via a checkbox, but it only toggles off the first time you click the checkbox. Any subsequent clicks do nothing. The KML layer just disappears. I have a feeling that this is probably an easy javascript fix, but I'm new to javascript and I can't figure it out. Anyone know what I'm doing wrong? Thanks in advance for your help.
Here's all my code:
<script type="text/javascript">
function initialize() {
var map;
var omaha = new google.maps.LatLng(41.265437, -95.947405);
var MY_MAPTYPE_ID = 'blue';
var stylez = [
{
featureType: "all",
stylers: [
{ hue: "#004A96" },
]
},
{
featureType: "all",
elementType: "labels",
stylers: [
{ hue: "#000000" },
]
},
{
featureType: "road",
elementType: "local",
stylers: [
{ hue: "#24356B" },
{ saturation: 55 },
{ lightness: 20 }
]
},
{
featureType: "poi.school",
elementType: "geometry",
stylers: [
{ hue: "#24356B" },
{ saturation: 55 },
{ lightness: 20 }
]
}
];
var imageBounds = new google.maps.LatLngBounds(
new google.maps.LatLng(41.2599,-95.9601),
new google.maps.LatLng(41.2718,-95.9367));
var mapOptions = {
zoom: 15,
center: omaha,
mapTypeControlOptions: {
mapTypeIds: [google.maps.MapTypeId.ROADMAP, MY_MAPTYPE_ID]
},
mapTypeId: MY_MAPTYPE_ID
};
var map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
var styledMapOptions = {
name: "Blue"
};
var jayzMapType = new google.maps.StyledMapType(stylez, styledMapOptions);
map.mapTypes.set(MY_MAPTYPE_ID, jayzMapType);
var oldmap = new google.maps.GroundOverlay(
"http://www.mcography.com/beta/CampusMap.png",
imageBounds);
oldmap.setMap(map);
var kmlLayer01URL = 'http://www.mcography.com/beta/CUADA.kml';
var kmlOptions = {
preserveViewport: 1
};
kmlLayer01 = new google.maps.KmlLayer(kmlLayer01URL, kmlOptions);
kmlLayer01.setMap(map);
// initially show KML Layer 01
document.getElementById('show_hide_KML_Layer_01').checked = true;
}
function toggleKMLLayer01() {
if (!document.getElementById('show_hide_KML_Layer_01').checked)
kmlLayer01.setMap(null);
else
kmlLayer01.setMap(map); }
</script>
</head>
<body onload="initialize()">
<p><input type="checkbox" id="show_hide_KML_Layer_01" onclick="toggleKMLLayer01();" />ADA Layer</p>
<div id="map_canvas"></div>
</body>
Without the top part of your code, I can't be totally sure, but my hunch is that you need to make the map variable global, otherwise toggle won't setMap to map. I wrote the following, which works:
var map;
function initialize() {
var mapOptions = { center: new google.maps.LatLng(0.0, 0.0), zoom: 2,
mapTypeId: google.maps.MapTypeId.ROADMAP };
map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
var kmlLayer01URL = 'http://www.mcography.com/beta/CUADA.kml';
var kmlOptions = {
preserveViewport: 1
};
kmlLayer01 = new google.maps.KmlLayer(kmlLayer01URL, kmlOptions);
kmlLayer01.setMap(map);
// initially show KML Layer 01
document.getElementById('show_hide_KML_Layer_01').checked = true;
}
function toggleKMLLayer01() {
if (!document.getElementById('show_hide_KML_Layer_01').checked)
kmlLayer01.setMap(null);
else
kmlLayer01.setMap(map);
}
I am trying to add an idle listener to google maps.
Problem: When I added the listener as shown below, I get the error Cannot read property '__e3_' of undefined
JS Code
google.maps.event.addListener(map, 'idle', function() {
console.log('hello');
}
I solved it by adding a setTimeout(..., 1000), to make sure the map is loaded after a sec.
Question:
Is the error due to the map not being loaded?
Is this the best way to solve it?
Is this problem supposed to occur? I am guessing that if I added this same listener to map without other code, this error will not popup.
EDIT
Initialization of Map
<script type="text/javascript">
var map;
var geocoder;
var directionsService = new google.maps.DirectionsService();
function initialize() {
var center_latlng = new google.maps.LatLng(42.354183,-71.065063);
var options = {
zoom: 15,
minZoom: 11,
maxZoom: 19,
center: center_latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map_canvas"), options);
var Style = [
{
featureType: "poi",
elementType: "labels",
stylers: [
{ visibility: "off" }
]
},{
featureType: "landscape",
elementType: "labels",
stylers: [
{ visibility: "off" }
]
}
]
map.setOptions({styles: Style});
geocoder = new google.maps.Geocoder();
// Marker Clusterer
var styles = {styles: [{
height: 34,
url: "images/template/markers/cluster.png",
width: 34,
textColor: '#FFF',
textSize: 12
},
{
height: 56,
url: "http://google-maps-utility-library-v3.googlecode.com/svn/trunk/markerclusterer/images/m2.png",
width: 56
},
{
height: 66,
url: "http://google-maps-utility-library-v3.googlecode.com/svn/trunk/markerclusterer/images/m3.png",
width: 66
},
{
height: 78,
url: "http://google-maps-utility-library-v3.googlecode.com/svn/trunk/markerclusterer/images/m4.png",
width: 78
},
{
height: 90,
url: "http://google-maps-utility-library-v3.googlecode.com/svn/trunk/markerclusterer/images/m5.png",
width: 90
}]
};
var mcOptions = {gridSize: 50, maxZoom: 15, styles: styles['styles']};
mc = new MarkerClusterer(map, [], mcOptions);
}
</script>
1.) Not exactly, This type of error is occurring because you are trying to access an object that doesn't exist at the time you try to attach the listener. The listener code must be attached after the map variable contains the Google map object. When are you trying to attach the listener? I do not see it in the initialization code.
2.) No, timeouts are not reliable. If there is a delay in the initialization the map object may still not be initialized at the specified interval.
3.) You can not access properties of an object that doesn't exist. Adding the listener in the init method after the map object is instantiated will solve this problem.
var map;
function initialize() {
var center_latlng = new google.maps.LatLng(42.354183, -71.065063);
var options = {
zoom: 15,
minZoom: 11,
maxZoom: 19,
center: center_latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
//instantiate map object
map = new google.maps.Map(document.getElementById("map_canvas"), options);
//attach listener to the map object.
google.maps.event.addListener(map, 'idle', function() {
console.log('hello');
});
}
here is a working fiddle with the above code: http://jsfiddle.net/R7d6L/