google map infoBoxes doesn't pop up consistently during mouseover - javascript

I have a google map embedded in xhtml. It has markers with popup InfoBoxes that I converted from InfoWindows to take advantage of layout control, but now I'm getting some inconsistent behavior. When the page first loads the infoBoxes all open normally with mouseover. But as I move around the map or move the cursor off the map and back on, they start behaving badly, sometimes they work, sometimes not.
/* map stuff */
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 4,
center: new google.maps.LatLng(41.40, -91.32),
mapTypeId: google.maps.MapTypeId.HYBRID
});
google.maps.event.trigger(map, 'resize');
map.setZoom( map.getZoom() );
var marker;
/* load each marker with info */
function addEvents(lat, lng, markerInfo) {
/* set each marker */
marker = new google.maps.Marker({
position: new google.maps.LatLng(lat, lng),
map: map
});
var iconFile = '#{request.contextPath}/img/pin.png';
marker.setIcon(iconFile);
/* infoBox properties - tried moving this to global, doesn't work */
var boxOpts = {
disableAutoPan: false,
maxWidth: 0,
pixelOffset: new google.maps.Size(-140, 0),
boxStyle: {
background: '#ffffff',
opacity: 1,
width: '180px'
},
closeBoxURL: '',
infoBoxClearance: new google.maps.Size(1, 1),
isHidden: false,
pane: 'floatPane',
enableEventPropagation: true
};
var infobox = new InfoBox(boxOpts);
var html = '<div style="color:#333; font-size:12px; box-shadow: 12px 12px 8px 4px rgba(0,0,0,0.4);">' markerInfo + '</div>';
/* mouseover shows infoBox - only works sometimes, tried addListener as well */
google.maps.event.addDomListener(marker, 'mouseover', function(){
infobox.setContent(html);
infobox.open(map, this);
});
google.maps.event.addDomListener(marker, 'mouseout', function(){
infobox.close(map, this);
});
}
the addEvents function is called here:
<div id="myController" style="visibility: hidden;">
<rich:dataList var="eventAdd" value="#{some.resultList}">
<script type="text/javascript">
addEvents('<h:outputText value="#{eventAdd.latitude}"/>',
'<h:outputText value="#{eventAdd.longitude}"/>',
'<h:outputText value="#{eventAdd.markerInfo}"/>
);
</script>
There doesn't appear to be any pattern to why some work and some don't, it's not always the same ones. I can mouseover one and the infoBox shows, move to another and it doesn't, move back to the previous one and it doesn't show either.
ETA:
When I go back to InfoWindow, the popups show as expected.

Related

How to change the default Marker used in the Google Maps API Drawing Layer controls

I would like to know how could I use a custom marker with google maps drawing controls. I want to do that because I need to place a marker when a user clicks in the map and have it open a info window (when clicked) and have a few custom actions in there (buttons and such).
I'm using react and #react-google-maps/api for this, but that might be besides the point since it is just a wrapper around the Maps Javascript API provided by Google.
From the docs it is possible to provide google.maps.MarkerOptions to the google.maps.drawing.DrawingManagerOptions. Unfortunately there is no option there to provide a custom Marker to be rendered.
I tried using the markercomplete() call back exposed by the google.maps.drawing.DrawingManager since it has the newly created Marker as parameter, and then doing something like this:
const handleNewMarker = (marker) => {
marker.addListener('click', function() {
setActiveMarker(marker);
});
}
My map component would then be something like this:
<GoogleMap
zoom={18}
center={latLng}
>
{activeMarker && <CustomInfoWindow anchor={activeMarker} />}
<DrawingManager
options={{
markerOptions: {
clickable: true,
draggable: true,
},
}}
onMarkerComplete={handleNewMarker}
/>
</GoogleMap>
Although this worked, it is not at all viable for production, for some reason the InfoWindow takes too much time to appear in the screen, that approach might be causing a memory leak and I don`t know why.
I might be missing something here, but on my research I didn't find a single soul trying to create a custom marker with the drawing tool, just custom markers by themselves which is relatively easy to do. My ideal case scenario, since I'm using React, would be to create a CustomMarker component with a CustomInfoWindow inside it, and just tell the drawing controls, "hey, take this marker and use it whenever a user tries to draw a new marker with your drawing tool".
Thank you.
Edit
Here is a screenshot of what I mean, that marker in the screen shot was placed there using the "new marker" drawing control, and I need the "new marker" drawing control to place a custom marker defined by me.
All you need to do is to set the icon property in the MarkerOptions, if I correctly understand your meaning of "custom marker". Below is an example using a SVG path for the icon.
This snippet is in full JS but the same should work with the React library.
var map;
function initialize() {
var mapOptions = {
center: new google.maps.LatLng(-34.397, 150.644),
zoom: 8
};
map = new google.maps.Map(document.getElementById('map'), mapOptions);
var drawingManager = new google.maps.drawing.DrawingManager({
drawingControl: true,
drawingControlOptions: {
position: google.maps.ControlPosition.TOP_CENTER,
drawingModes: [google.maps.drawing.OverlayType.MARKER]
},
markerOptions: {
draggable: false,
icon: {
path: "M-20,0a20,20 0 1,0 40,0a20,20 0 1,0 -40,0",
fillColor: '#FF0000',
fillOpacity: 0.6,
anchor: new google.maps.Point(0, 0),
strokeWeight: 0,
scale: 1
}
}
});
drawingManager.setMap(map);
}
#map {
height: 180px;
}
<div id="map"></div>
<!-- Replace the value of the key parameter with your own API key. -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initialize&libraries=drawing" async defer></script>
Now if you need the marker to be clickable, have an Infowindow, etc. do you really need to use the drawing manager? Could you not simply listen for a map click event, and create a standard marker?
Or possibly, use both? (Create the marker with the drawing manager and convert it to a standard marker by the use of the markercomplete event, which seems to be more or less what you are doing.)
Edit:
If you need to create a "real" marker with an InfoWindow, you can do it in the markercomplete event.
var map;
var infowindow;
function initialize() {
var mapOptions = {
center: new google.maps.LatLng(-34.397, 150.644),
zoom: 8
};
map = new google.maps.Map(document.getElementById('map'), mapOptions);
infowindow = new google.maps.InfoWindow();
var drawingManager = new google.maps.drawing.DrawingManager({
drawingControl: true,
drawingControlOptions: {
position: google.maps.ControlPosition.TOP_CENTER,
drawingModes: [google.maps.drawing.OverlayType.MARKER]
}
});
drawingManager.setMap(map);
google.maps.event.addListener(drawingManager, 'markercomplete', function(marker) {
// Remove overlay from map
marker.setMap(null); // Optional, but this will remove the drawn marker
drawingManager.setDrawingMode(null); // Optional, but this will "disable" the drawing tools
// Create the "real" marker
createMarker(marker.getPosition());
});
}
function createMarker(position) {
var marker = new google.maps.Marker({
position: position,
map: map,
title: 'Custom marker',
icon: {
path: "M-20,0a20,20 0 1,0 40,0a20,20 0 1,0 -40,0",
fillColor: '#FF0000',
fillOpacity: 0.6,
anchor: new google.maps.Point(0, 0),
strokeWeight: 0,
scale: 1
}
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent('This is the content');
infowindow.open(map, this);
});
}
#map {
height: 180px;
}
<div id="map"></div>
<!-- Replace the value of the key parameter with your own API key. -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initialize&libraries=drawing" async defer></script>

Adding Google Maps InfoWindow from data features generates error: "b.get is not a function"

I'm trying to add a info window to each of my features in a Google Map. In the example from Google (https://developers.google.com/maps/documentation/javascript/infowindows) They add an info window directly to a marker. I don't have a explicit market to add my info window, instead I have a collection of data that I imported from a GeoJson file.
I can add a click listener to each feature, and create a new InfoWindow with the correct description. However, I get an error (b.get is not a function) when opening the InfoWindow.
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
zoom: 2,
center: new google.maps.LatLng(28.7, -15.0),
mapTypeId: 'terrain'
});
map.data.loadGeoJson('http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/4.5_week.geojson');
map.data.setStyle(function (feature) {
var magnitude = feature.getProperty('mag');
return {
icon: getCircle(magnitude)
};
});
map.data.addListener('click', function (event) {
var infowindow = new google.maps.InfoWindow({
content: event.feature.getProperty('place')
});
infowindow.open(map, event.feature);
});
The error I get with the posted code (once I include all the missing pieces) is Uncaught TypeError: b.get is not a function
The second parameter of the InfoWindow.open method is required to be a MVCObject that exposes a LatLng position property, the only one of which in the core API is a google.maps.Marker (not a event.feature)
from the documentation:
open(map?:Map|StreetViewPanorama, anchor?:*) | Return Value: None
Opens this InfoWindow on the given map. Optionally, an InfoWindow can be associated with an anchor. In the core API, the only anchor is the Marker class. However, an anchor can be any MVCObject that exposes a LatLng position property and optionally a Point anchorPoint property for calculating the pixelOffset (see InfoWindowOptions). The anchorPoint is the offset from the anchor's position to the tip of the InfoWindow.
The work around is to set the position of the InfoWindow:
map.data.addListener('click', function(event) {
var infowindow = new google.maps.InfoWindow({
content: event.feature.getProperty('place')
});
infowindow.setPosition(event.latLng);
infowindow.open(map);
});
proof of concept fiddle
code snippet:
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
zoom: 2,
center: new google.maps.LatLng(28.7, -15.0),
mapTypeId: 'terrain'
});
map.data.loadGeoJson('http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/4.5_week.geojson');
map.data.setStyle(function(feature) {
var magnitude = feature.getProperty('mag');
return {
icon: getCircle(magnitude)
};
});
map.data.addListener('click', function(event) {
var infowindow = new google.maps.InfoWindow({
content: event.feature.getProperty('place')
});
infowindow.setPosition(event.latLng);
infowindow.open(map);
});
}
google.maps.event.addDomListener(window, "load", initMap);
// from google sample at: https://developers.google.com/maps/documentation/javascript/earthquakes
function getCircle(magnitude) {
return {
path: google.maps.SymbolPath.CIRCLE,
fillColor: 'red',
fillOpacity: .2,
scale: Math.pow(2, magnitude) / 2,
strokeColor: 'white',
strokeWeight: .5
};
}
html,
body,
#map {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
<div id="map"></div>

Google Maps Infobox on Custom HTML Marker

I'm trying to get an infobox to open after clicking an overlay(custom HTML marker).
This map shows a typical marker and a customer HTML marker. When I click the typical marker, the infobox opens correctly. When I click the custom HTML marker, the infobox doesn't open with error msg: TypeError: anchor.getPosition is not a function. This relates to the incorrect parameters I'm passing to infobox.open(). It expects a marker, but since I'm clicking an overlay (custom HTML marker), the parameter passed is incorrect.
How can I adjust the infobox.open() function so that it accepts my overlay as a parameter?
<!DOCTYPE html>
<html>
<style>
#map{
height: 600px;
width: 600px;
}
</style>
<body>
<div id="map"></div>
<script src="https://maps.google.com/maps/api/js?sensor=false"></script>
<script src="https://google-maps-utility-library-v3.googlecode.com/svn/trunk/infobox/src/infobox.js"></script>
<script src="....path/to/custom-html-markers-google-maps.js"></script>
<script>
var infobox = new InfoBox({
disableAutoPan: false,
maxWidth: 300,
pixelOffset: new google.maps.Size(-75, -70),
zIndex: null,
boxStyle: {width: '150px'},
infoBoxClearance: new google.maps.Size(15, 50)
});
function initialize() {
var loc = new google.maps.LatLng(-33.89, 151.26);
var locMarker = new google.maps.LatLng(-33.89, 151.23);
var map = new google.maps.Map(document.getElementById("map"), {
zoom: 12,
center: loc,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
//This works FINE.. It sets the marker and infobox listener
var marker = new google.maps.Marker({
map: map,
position: locMarker,
visible: true
});
google.maps.event.addListener(marker, 'click', function() {
infobox.setContent('<div style="background-color:yellow">This is<br>an infobox.</div>');
infobox.open(map, this);
});
//Overlay from: http://humaan.com/custom-html-markers-google-maps/
var overlay = new CustomMarker(loc, map, {marker_id: '123'});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</body>
</html>
Part of Custom HTML Marker script:
google.maps.event.addDomListener(div, "click", function(event) {
infobox.setContent('<div style="background-color:yellow">Hi there</div>');
infobox.open(map, this); //*******THIS IS THE PROBLEM********
google.maps.event.trigger(self, "click");
});
My problem is infobox.open(map, this); is expecting a marker and I give it the "div". How can I adjust this function so that it accepts my div?
Full script: http://humaan.com/custom-html-markers-google-maps/
To use anything as an anchor for a marker, it needs to expose a latLng position property and an optional anchorPoint property.
from the documentation:
open(map?:Map|StreetViewPanorama, anchor?:MVCObject)
Return Value: None
Opens this InfoWindow on the given map. Optionally, an InfoWindow can be associated with an anchor. In the core API, the only anchor is the Marker class. However, an anchor can be any MVCObject that exposes a LatLng position property and optionally a Point anchorPoint property for calculating the pixelOffset (see InfoWindowOptions). The anchorPoint is the offset from the anchor's position to the tip of the InfoWindow.
I wasn't carrying the correct loc(lat/lng) and map into the function call.
Here is the revised listener:
google.maps.event.addDomListener(div, "click", function(event) {
var map = self.getMap();
var loc = self.latlng;
infobox.setContent('<div style="background-color:yellow">Hi there</div>');
infobox.openRevised(map, this, loc);
google.maps.event.trigger(self, "click");
});
Here is the revised infobox.open() function:
InfoBox.prototype.openRevised = function (map, anchor, loc) {
if (anchor) {
this.position_ = loc;
}
this.setMap(map);
};

google maps api v3 trigger street view on link click

I'm recently new in the google map api v3, and wanted to ask if there is any way I could trigger the street view mode just by clicking a link in my infoBox.
so far this is my code:
var map;
var marker;
var infowindow;
function HomeControl(controlDiv, map) {controlDiv.style.margin = '50px 0 0 0';}
function initialize() {
var location = new google.maps.LatLng(37.78391, -122.407157);
var mapOptions = {
center: location,
zoom: 18,
panControl: false,
scrollwheel: false,
zoomControl: false,
scaleControl: true,
streetViewControl: true,
streetViewControlOptions: {
mapTypeControl: true,
mapTypeId: google.maps.MapTypeId.ROADMAP };
map = new google.maps.Map(document.getElementById('map-canvas'),
mapOptions);
marker = new google.maps.Marker({position: map.getCenter(),
map: map,
title: 'Click to zoom'
});
var boxText = document.createElement("div");
boxText.style.cssText = "margin-top: 26px; background: url('inc/images/infowindow-overlay.png') repeat left top; padding: 15px 20px;";
boxText.innerHTML = "<span class='pointing-arrow'></span><h2 class='adress-title'>San Francisco Center</h2><a href='#'>Centre Website</a><a href='#'>Street View</a>";
var myOptions = {
content: boxText,
disableAutoPan: false,
maxWidth: 0,
pixelOffset: new google.maps.Size(-5, 0),
zIndex: null,
boxStyle: {width: "280px"}
};
map = new google.maps.Map(document.getElementById("map-canvas"),
mapOptions);
var image = 'inc/images/westfield-marker-logo.png';
marker = new google.maps.Marker({
position: location,
map: map,
title: 'Westfield HQ',
draggable: true,
icon: image
});
//infowindow.open(map,marker);
google.maps.event.addListener(marker, 'click', function() {
map.setZoom(18);
map.setCenter(marker.getPosition());
ib.open(map, this);
});
var ib = new InfoBox(myOptions);
}
google.maps.event.addDomListener(window, 'load', initialize);
now what I want to do is that, in the part where I initialize the boxText, and add the mark-up, i want the street view anchor tag to initialize the street view onclick.
I've found some options in the documentation like centering the map to the marker by clicking external links, but couldn't find any to activate the street view on click.
The way to handle a click event on an element inside an InfoBox (or an InfoWindow) is a little convoluted.
Here's a JSFiddle to demonstrate how it's done. DEMO
Basically, you write your click handler like this:
google.maps.event.addDomListener(ib.content_,'click',(function(marker) {
return function() {
openStreetView(); // Here's where you activate the StreetViewPanorama
}
})(marker));
I didn't include details about how to activate a StreetViewPanorama through code, since there's plenty of information on that subject in the Google Maps JS API Docs.
EDIT
I just realized that this handler runs anytime you click anything inside the InfoBox which is not exactly what you asked for. To achieve exactly what you want (event handler on the 'Street View' link inside the InfoBox), I had to use a little jQuery. Here's the updated fiddle: DEMO
Here, you create the content of the InfoBox as a jQuery element, so you can bind a click handler to the 'Street View' link. (I gave #swl as an id to that link, so I could find it with jQuery.)
var boxObj = $("<div style='margin-top: 26px; background: url('inc/images/infowindow-overlay.png') repeat left top; padding: 15px 20px;'><span class='pointing-arrow'></span><h2 class='adress-title'>San Francisco Center</h2><a href='#'>Centre Website</a><a href='#' id='swl'>Street View</a></div>");
boxObj.find('#swl').on('click', function(){
openStreetView();
});
It's not the prettiest code (you should create a css class and move all style definitions under that class) but it gets the job done. I'm sure you can clean it up and make it production worthy :)

Google Map loading partially on click on the hidden tab

I'm using 2 tabs, first for showing list and another showing map.
When the first time page is loaded 1 tab is shown by default and on click of second tab map is shown, but when i click list tab and again click map tab map loading partially.
Here is my JAVASCRIPT code:
$(document).on('click', "#load-map-view", function() {
locateStores();
$("#store-list-view").hide();
$("#store-list-view").removeClass('disabled');
$("#store-map-view").show();
$("#store-map-view").addClass('disabled');
});
function locateStores() {
var mapContent;
var map = new google.maps.Map(document.getElementById("store-map-view"), {
center: new google.maps.LatLng(47.6145, -122.3418),
mapTypeId: google.maps.MapTypeId.ROADMAP,
zoom: 13
});
var markers = [];
$("#store-list-view .listed-shop").each(function() {
markers.push({
lat: $(this).attr('data-lat'),
lng: $(this).attr('data-lan'),
name: $.trim($(this).find('div.shop-name').text())
});
});
for (index in markers)
addMarker(markers[index]);
function addMarker(data) {
var marker = new google.maps.Marker({
position: new google.maps.LatLng(data.lat, data.lng),
map: map,
title: data.name
});
var infobox = new InfoBox({
content: document.getElementById("infobox"),
disableAutoPan: false,
maxWidth: 150,
pixelOffset: new google.maps.Size(-140, -10),
zIndex: null,
boxStyle: {
background: "url('http://google-maps-utility-library-v3.googlecode.com/svn/trunk/infobox/examples/tipbox.gif') no-repeat",
opacity: 0.80,
width: "400px"//"280px"
},
closeBoxMargin: "12px 4px 2px 2px",
closeBoxURL: "http://www.google.com/intl/en_us/mapfiles/close.gif",
infoBoxClearance: new google.maps.Size(1, 1)
});
google.maps.event.trigger(map, 'resize');
map.setZoom(map.getZoom());
google.maps.event.addListener(marker, 'click', function() {
$(".infoBox").fadeOut(300);
infobox.open(map, this);
map.panTo(new google.maps.LatLng(47.6145, -122.3418));
});
}
var bounds = new google.maps.LatLngBounds();
for (index in markers) {
var data = markers[index];
bounds.extend(new google.maps.LatLng(data.lat, data.lng));
}
map.fitBounds(bounds);
var pin = new google.maps.MVCObject();
function openInfoWindow(marker) {
title.innerHTML = marker.getTitle();
pin.set("position", marker.getPosition());
infowindow.open(map, marker);
}
}
I have tried several solutions like :
adding this code
google.maps.event.trigger(map, "resize");
and many other solutions, but still the page still isn't loading.
can someone help me out in this?
I have figured out the problem I was getting.
I was adding below code on wrong position:
google.maps.event.trigger(map, "resize");
The solution to my problem is:
If you are using map for hidden div. Declare map variable as global.
Then show the div first, load the map after div is shown and resize it using the code given.
var map; //globalize your map variable
// Then do the necessary loading
$(document).on('click', "#load-map-view", function() {
$("#store-list-view").hide();
$("#store-list-view").removeClass('disabled');
locateStores();
google.maps.event.trigger(map, "resize");
$("#store-map-view").show();
$("#store-map-view").addClass('disabled');
});

Categories