I'm having trouble getting the infoboxes for the bing API to open on click from outside the map.
Here is the show infobox function and the function to create the pin/infobox itself:
function displayInfobox(e) {
pinInfobox.setOptions({
title: e.target.Title,
description: e.target.Description,
visible: true,
offset: new Microsoft.Maps.Point(0, 25)
});
pinInfobox.setLocation(e.target.getLocation());
}
function hideInfobox(e) {
pinInfobox.setOptions({
visible: false
});
}
function displayPinsOnMap(results) {
// Creates a collection to store multiple pins
var pins = new Microsoft.Maps.EntityCollection();
//Create the info box for pushpin
var infoboxOptions = {width: 260, height:160};
pinInfobox = new Microsoft.Maps.Infobox(new Microsoft.Maps.Location(0, 0), infoboxOptions);
infoboxLayer.push(pinInfobox);
// Create Pins
for (var i = 0; i < results.length; i++) {
//pushpin location
var position = new Microsoft.Maps.Location(results[i]["Lat"], results[i]["Lon"]);
//Create the pin
if(results[i]["DNC"] == 'DNC') {
var sppins = {htmlContent:"<img src='badsp.png' height='32px'> " };
} else {
var sppins = {htmlContent:"<img src='sppin.png' height='32px'> " };
}
var pin = new Microsoft.Maps.Pushpin(position, sppins);
pin.Title = results[i]["Business Name"];
pin.Description =results[i]["Address"] + "<br>" +
results[i]["City"] + ", " +
results[i]["StateListing"] + "<br>" +
results[i]["Phone"] +
"<br>Fax: " + results[i]["Fax"] +
"<br>Email: " + results[i]["Email"];
Microsoft.Maps.Events.addHandler(pin, 'click', displayInfobox);
function pinclick(i) {
Microsoft.Maps.Events.addHandler(results[i], 'click');
}
//Add pin to the map
map.entities.push(pin);
}
//hide box on map move
Microsoft.Maps.Events.addHandler(map, 'viewchange', hideInfobox);
//add pins/infobox
map.entities.push(pinInfobox);
}
I have a list of items pulled from a JSON file and displayed on the map. Each item creates a pin and info box as well as in a table off to the side of the map. What I need to be able to do is on click of the name of the company from the table I need it to open up the infobox associated with that company. Here is how I did it in the past with Google API - this doesn't seem to work in the same way for Bing (yes I have to use bing).
"<td>"+'<a href="#" onclick="javascript:displayInfobox(' + (i) + ');">' + results[i]["Business Name"] +'<\/a>' + "</td>"
It looks like you have copied the displayInfobox function from some code that is expecting to be trigerred when someone clicks a pushpin because that function has this code:
pinInfobox.setLocation(e.target.getLocation());
the getLocation() method exists on Bing Maps pushpin object but obviously not on your so it will be failing when it gets to that line (your using your browsers debug tools right?). You will need to change that line so that it gets the location for the infobox to show from somewhere, either by having the lat lon as some attribute on your and constructing a new Bing Maps location object using those or by looping through all the pins on the map to find that one that matches your in some way
Related
I get the below error message from the console when I try to implement Google Maps to my Qualtrics survey. API Key works properly:
"This site overrides Array.from() with an implementation that doesn't
support iterables, which could cause Google Maps JavaScript API v3 to
not work correctly."
AND this is my code (ignore my API key):
I am not using any array, so I am not sure where the problem is coming from...
/*
* Qualtrics Google Map Lat/Long Collector
* Version 1.4
*
* Written by George Walker <george#georgewwalker.com>
* Get the latest from GitHub: https://github.com/pkmnct/qualtrics-google-map-lat-long/releases
*
* This JavaScript allows a Qualtrics user to collect a lat/long from a
* Google Map in a survey. To use it, create a new "Text Entry" question,
* then add this JavaScript to the question. You can set variables below.
* These include the lattitude and longitude to center the map at, the
* zoom level of the map, and the text to display when hovering over the
* map's pin. It also includes the width and height of the map.
*/
// Enter your Google Map API key in this variable:
var googleMapAPIKey = "MyKey";
Qualtrics.SurveyEngine.addOnload(function() {
// --- User Variables, set these: ---
var mapCenterLat = 39.1836;
var mapCenterLng = -96.5717;
var mapZoom = 16; // See https://developers.google.com/maps/documentation/javascript/tutorial#zoom-levels for help.
var pinTitle = "Move pin to correct location"; // This is displayed when hovering over the pin on the map.
var mapWidth = "100%";
var mapHeight = "300px";
var locationInputWidth = "96%";
var locationInputMargin = "2%";
var locationInputPadding = "15px";
var enableAutocompleteField = true;
var invalidLocationAlertText = "Please choose a location from the search dropdown. If your location doesn't appear in the search, enter a nearby location and move the pin to the correct location.";
// --- End of User Variables ---
// Get the data entry box and store it in a variable
var dataBox = document.getElementById("QR~" + this.questionId);
// Get the question container and store it in a variable.
var questionContainer = this.getQuestionContainer();
// Need to be able to access the marker to update it later.
var marker;
if (enableAutocompleteField) {
// Create a search box
try {
var locationInput = document.createElement('input');
locationInput.setAttribute("id", this.questionId + "-locationInput");
locationInput.style.width = locationInputWidth;
locationInput.style.margin = locationInputMargin;
locationInput.style.padding = locationInputPadding;
questionContainer.appendChild(locationInput);
var locationInputID = this.questionId + "-locationInput";
} catch (err) {
console.log("Unable to create places autocomplete field. Details: " + err);
alert("An error occurred creating the input field.");
}
}
try {
// Create a map object and append it to the question container.
var mapObject = document.createElement('div');
mapObject.setAttribute("id", this.questionId + "-map");
mapObject.style.width = mapWidth;
mapObject.style.height = mapHeight;
questionContainer.appendChild(mapObject);
var mapID = this.questionId + "-map";
} catch (err) {
console.log("Unable to create map object. Details: " + err);
alert("An error occurred creating the map.");
}
// Hide the data box
try {
dataBox.style.display = 'none';
} catch (err) {
console.log("Unable to hide data box.");
}
// This function calls itself once per second until the Google Maps API is loaded, then it displays the map.
function displayMap() {
try {
if (enableAutocompleteField) {
var locationAutocomplete = new google.maps.places.Autocomplete(locationInput);
// Whenever the inputs change, set the locationLatLong
google.maps.event.addListener(locationAutocomplete, 'place_changed', function() {
var place = locationAutocomplete.getPlace();
if (!place.geometry) {
alert(invalidLocationAlertText);
} else {
var locationLatLong = new google.maps.LatLng(place.geometry.location.lat(), place.geometry.location.lng());
marker.setPosition(locationLatLong);
map.panTo(locationLatLong);
dataBox.value = '{"lat": "' + place.geometry.location.lat() + '", "long": "' + place.geometry.location.lng() + '"}';
}
});
}
var map = new google.maps.Map(document.getElementById(mapID), {
center: {
lat: mapCenterLat,
lng: mapCenterLng
},
zoom: mapZoom
});
// Create a new marker in the center of the map.
marker = new google.maps.Marker({
draggable: true,
position: {
lat: mapCenterLat,
lng: mapCenterLng
},
map: map,
title: pinTitle
});
// When the pin is clicked, store the lat/lng
google.maps.event.addListener(marker, 'click', function(event) {
dataBox.value = '{"lat": "' + this.getPosition().lat() + '", "long": "' + this.getPosition().lng() + '"}';
});
// When the pin is dragged, store the lat/lng where it ends
google.maps.event.addListener(marker, 'dragend', function(event) {
dataBox.value = '{"lat": "' + this.getPosition().lat() + '", "long": "' + this.getPosition().lng() + '"}';
});
} catch (err) {
setTimeout(displayMap, 1000);
}
}
displayMap();
});
// Load the Google Maps API if it is not already loaded.
try {
if (typeof googleMapJS == 'undefined') {
var googleMapJS;
if (googleMapJS == null) {
googleMapJS = document.createElement('script');
if (googleMapAPIKey == "MyKey" || googleMapAPIKey == null) {
googleMapJS.src = 'https://maps.googleapis.com/maps/api/js?key=MyKey';
} else {
googleMapJS.src = 'https://maps.googleapis.com/maps/api/js?key=MyKey';
//googleMapJS.src = 'https://maps.googleapis.com/maps/api/js?key=' + googleMapAPIKey;
}
document.head.appendChild(googleMapJS);
}
} else {
console.log("Map already loaded.");
}
} catch (err) {
console.log("Unable to load Google Maps API. Details: " + err);
alert("Unable to load Google Maps API.");
}
A similar issue has been reported in our Public Issue Tracker and already been addressed by our Engineering team. As per latest comment:
We've just submitted an update for this. The check is now more
explicit and will cover your use case: Array.from(new Set([42]))[0]
!== 42 ... warn
This will be available in an upcoming weekly release
Public Issue Tracker is a tool used internally at Google to track bugs and feature requests during product development. It is available outside of Google for use by external public and partner users who need to collaborate with Google teams on specific projects. You can learn more here https://developers.google.com/issue-tracker/.
I found the same errors. I used Mootols Lightbox and Google Map framework together on my website. The Mootols had a javascript conflict with Google scripts. I removed the Mootols script and this Google message disappeared and Google Map works perfectly now.
I have created multiple infoboxes using BingMaps V8 API.
The issue that I am facing here is when the infobox is towards the corners of the map, the details from infobox is trimmed.
infobox being trimmed. I want to autopan the :
Code :
var ParseLatLogXml = function(xml, address){
if(typeof xml.resourceSets["0"].resources === "undefined" || xml.resourceSets["0"].resources.length === 0)
{
console.log("Lat Long of Address not found: " + address);
return [];
}
return [ xml.resourceSets["0"].resources["0"].geocodePoints["0"].coordinates["0"],
xml.resourceSets["0"].resources["0"].geocodePoints["0"].coordinates["1"] ];
};
var AddStore = function( storeNumb ,storeID, storeName, city, state, addr, phone, zip, distance, lat, long){
var _loc = new Microsoft.Maps.Location(parseFloat(lat), parseFloat(long));
var _pin = new Microsoft.Maps.Pushpin(_loc, {
icon: '-/media/1044109b112b479bb98e4daf6154e817.ashx',
anchor: new Microsoft.Maps.Point(20, 20)
}
);
var adder = addr + '\r\n' + city + '\r\n' + zip + state + "\r\n" + storeName
// Create the infobox for the pushpin
var _infoBox = new Microsoft.Maps.Infobox(_pin.getLocation(),
{ width: 300,
height: 150,
title: storeName,
description: distance + " miles" +'<br>' + addr +'<br>'+ city + " "+ zip +'<br>'+ phone ,
offset: new Microsoft.Maps.Point(10,15),
showCloseButton: false,
visible: false
});
// Add handler for the pushpin click event.
// Microsoft.Maps.Events.addHandler(_pin, 'click', displayInfobox);
Microsoft.Maps.Events.addHandler(_pin, 'mouseover', function () {
_infoBox.setOptions({ autoPan:true, visible: true });
});
Microsoft.Maps.Events.addHandler(_pin, 'mouseout', function () {
_infoBox.setOptions({ autoPan:true, visible: false });
});
map.entities.push(_pin); //[locNum]
_infoBox.setMap(map);
I tried using the auto pan which i am not sure if it would do the trick.
Can someone help me on this.
I also tried the re-positioning of the ifobox and that dinot help either.
I used below links for reference :
https://social.msdn.microsoft.com/Forums/sqlserver/en-US/cf803dd2-0f56-429e-863b-9f9a6480ff17/bing-maps-v8-api-repositioning-an-infobox?forum=bingmapsajax
There is no built in autopan or repositioning logic in the Infobox class in Bing Maps. The easiest solution would be to center the map on the pushpin when opening the infobox, although this would be better suited if using a click event to open the infobox rather than a mouseover event. Using mouseover/mouseout events would result in the infobox closing if the infoboxes position was changed.
Another option is to use the Custom Infobox module here: http://bingmapsv7modules.codeplex.com/wikipage?title=Custom%20Infobox%20Control The infobox in this module repositions how it is displayed based on where in the map the pushpin is. If the pushpin is in the top right corner, the infobox displays itself to the bottom left of the pushpin. You can find the source code for this module here: http://bingmapsv7modules.codeplex.com/SourceControl/latest#BMv7Plugins/BMv7.CustomInfobox/scripts/V7CustomInfobox.js
In order to add an offset to the center point in Google maps when a button are pressed, I try this funcion:
function offsetCenter(map, marker) {
var worldCoordinateCenter = map.getProjection().fromLatLngToPoint(marker.getPosition());
var pixelOffset = new google.maps.Point((100/scale) || 0,(0/scale) ||0)
var worldCoordinateNewCenter = new google.maps.Point(
worldCoordinateCenter.x - pixelOffset.x,
worldCoordinateCenter.y + pixelOffset.y
);
var newCenter = map.getProjection().fromPointToLatLng(worldCoordinateNewCenter);
map.setCenter(newCenter);
}
});
I call that funcion from infoWindows where map and marker are defined:
(function(marker, data) {
google.maps.event.addListener(marker, "click", function() {
info = '<h4>' + data.nombre + '</h4><h4>'+ data.offerta+'</h4><h4>'+ data.horario+'</h4><a href='+data.web+'><h4>Web</h4></a>'
+ '<input type="button" class = "launchConfirm" onclick="offsetCenter(\''+map+'\', \''+marker+'\');" value='Reset center'></input>' //this is the button inside the infowindos to re-set the map center with an offset
;
infoWindow.setContent(info);
infoWindow.open(map, marker);
map.setCenter(marker.getPosition()); //center the map to marker
map.setZoom(16); //zoom to marker
});
}
But marker and map object are not defined inside the offsetCenter function.
How can pass a map object and marker to that function?
make sure your 'map' variable and your marker manager are in scope >= function scope. this way you will not need to pass in the map.
Use a marker manager to manage your makers. you can then add a unique id to some attribute on your link. when the click comes in you can access the object to get the id, which will allow you to retrieve the maker from the manager. so the code would look something like this:
Info Window Content(shortened for brevity):
var info = '<h4>' + data.nombre + '</h4>'<input type="button" data-markerId="' + SomeMarkerManager.getMarkerId() '" onclick="offsetCenter(this);" value='Reset center'></input>'
var offsetCenter = function (element) {
// get the marker Id
var markerId = $(element).attr("data-marker-id");
// use the markerId to find your marker
var marker = SomeMarkerManager.getMarkerById(markerId);
// now you have access to your map and the clicked marker
}
P.S.
marker managers are out of the scope of this answer. Just search for google maps marker managers.
Since last monday we have problem in google maps. First of all, we use custom markers to show the results of a search "grouped" by concept, that's mean than we show a yellow box with a text and a number with its count. If you take a look at this image you will see the errors
(Link to the image at http://imgur.com/sa1PvQo )
In "Grierkenland (556)" or "Turkije (392)" markers there aren't any kind of image there (behold the red boxes)
In "Cyrpus (43)" you will see the image than i put in each marker but only on this marker appears. Appears too FOUR more images overlaped one each other (numbers 1 to 4 on the screenshot, the original image is the number 1, the rest is the same image overlap on each other)
We don't change anything for a month and, i said before, from this monday the marker's image doesnt work at all. Our code are:
Create the icon. Generates an object with the image's url (the pathPrefix is a string with some like "www.test.com", for ex.):
getLocIcon: function (markerLength) {
var markerSize = 100;
if (markerLength > 18) {
markerSize = 183;
} else if (markerLength > 15) {
markerSize = 146;
} else if (markerLength > 13) {
markerSize = 122;
}
icon =
{
url: priv.pathPrefix + '/images/googlemaps/loc-marker-' + markerSize + '.png',
anchor: new google.maps.Point(15, 0),
size: new google.maps.Size(markerSize, 22)
};
return icon;
},
Create the marker. Generates a marker object with all the information required, including the "icon" object:
createLinkMarker: function (gllPosition, strTargetText, strTargetLink, strMarkerToolTip) {
var locationMarkerText = "<nobr>" + strMarkerToolTip + " (" + strTargetText + ")</nobr>";
var otherOpts =
{
position: gllPosition,
map: priv.googleMap,
labelClass: "locationLabel",
icon: priv.getLocIcon((strMarkerToolTip + " (" + strTargetText + ")").length),
clickable: true,
draggable: false,
labelContent: locationMarkerText,
//anchorPoint: new google.maps.Point(15, 0),
title: strMarkerToolTip
};
var marker = new MarkerWithLabel(otherOpts);
google.maps.event.addListener(marker, 'click', function () {
location.href = strTargetLink;
});
return marker;
},
The rest of the code to include the markers inside google maps (priv.googleMap is the google map's object and markers are an array of marker getted from createLinkMarker function):
var markerMgrOptions = { maxZoom: priv.maxZoom, trackMarkers: false };
priv.markerManager = new MarkerManager(priv.googleMap, markerMgrOptions);
[ ... ]
priv.markerManager.clearMarkers();
priv.markerManager.addMarkers(markers, priv.minZoom, priv.maxZoom);
priv.markerManager.refresh();
Do you know if there are something new or a bad practice there?
Thanks in advance and regards.
I'm a beginner in google maps and JavaScript.
I'm creating a random markers on google map using Maps API V3, I want to create a list on the side that contain all Markers Id so when i click on Marker ID it will zoom in, on the map to show the marker. specifically i want to know how to create that link in javascript
thank you
This answer is from beginner to beginner ;) I like benastan's answer for succinctness and the application of closure, still I'd like to show a more "basic" approach by writing functions.
I don't feel qualified to talk about closures and function scopes, but I can say from experience these closure "wrappers" prevent unexpected behavior from functions called within loops or within other functions. One such bug could be a loop iterator value ending up all the same value (last iteration) or undefined. (my own example)
Link to full code: http://jsfiddle.net/WaWBw/
Click on the map to place markers, and clicking on markers or links on the side zooms in.
function addMarker(pos) {
var marker = new google.maps.Marker({
map: map,
position: pos
});
markers.push(marker);
count = markers.length - 1;
addMarkerListener(marker, count, 6);
makeDiv(count, 4, "Marker #");
count++;
}
function addMarkerListener(marker, index, zoomLevel) {
google.maps.event.addListener(marker, 'click', function(event) {
zoomIn(index, zoomLevel);
});
}
function makeDiv(index, zoomLevel, content) {
document.getElementById("sidebar").innerHTML += '<div onclick="zoomIn(' + index + ',' + zoomLevel + ')">' + content + ' ' + index + '</div>';
}
function zoomIn(index, zoomLevel) {
map.setCenter(markers[index].getPosition());
map.setZoom(zoomLevel);
}
Say you have a set of lat/lng coordinates:
var coords = [[32, -70], [50, -10], [0, 20]];
Loop through the coordinates, plotting the marker on your map and generating the list items. Bind the click handler at the same time:
var tpl = 'Click here to view a point';
// Loop through coordinates.
for (var i in coords) {
// Create a closure.
(function() {
var pt = coords[i],
latlng = new google.maps.LatLng(pt[0], pt[1]),
marker = new google.maps.Marker({
position: latlng,
map: map // variable containing your google map.
}),
elm = document.createElement('li');
elm.innerHTML = tpl;
// When you click the list item, set map center to latlng of marker.
elm.onclick = function() {
map.setCenter(latlng);
};
document.body.appendChild(elm);
})();
}