I'm using this script to show small info windows next to each respective map location, using the Google maps API.
The problem is as you click Location 01, Location 02 etc the small windows remain open and can easily appear over top of each other, which isn't very user friendly.
What I need to do is have it so that only one of the small info windows can be visible at any given time. So for example, if I click 'Location 01' then all other info windows that might have been open will close.
You can see the fiddle in action here: https://jsfiddle.net/vm4cksue/
...or view my code here...
(function($) {
function new_map( $el ) {
// var
var $markers = $el.find('.marker');
// vars
var args = {
//zoom : 14,
center : new google.maps.LatLng(0, 0),
scrollwheel : false,
mapTypeId : google.maps.MapTypeId.ROADMAP,
mapTypeControlOptions: {
style: google.maps.MapTypeControlStyle.HORIZONTAL_BAR,
position: google.maps.ControlPosition.TOP_RIGHT
}
};
// create map
var map = new google.maps.Map( $el[0], args);
// add a markers reference
map.markers = [];
// add markers
// add identifying number to each marker
var sidebar = 1;
$markers.each(function(){
add_marker( $(this), map, sidebar);
sidebar++;
});
// center map
center_map( map );
// return
return map;
}
function add_marker( $marker, map, sidebar ) {
// dynamic Lat & Long
var latlng = new google.maps.LatLng(
$marker.attr('data-lat'), $marker.attr('data-lng')
);
// Dynamic marker
var icon = $marker.attr('data-icon');
// create marker
var marker = new google.maps.Marker({
position: latlng,
map: map,
animation: google.maps.Animation.DROP, // animation
icon: icon,
});
// add to array
map.markers.push( marker );
// if marker contains HTML, add it to an infoWindow
if( $marker.html() )
{
// create info window
var infowindow = new google.maps.InfoWindow({
content : '<div id="iw-container">' + $marker.html() + '</div>'
});
/*
* The google.maps.event.addListener() event waits for
* the creation of the infowindow HTML structure 'domready'
* and before the opening of the infowindow defined styles
* are applied.
*/
google.maps.event.addListener(infowindow, 'domready', function() {
// Reference to the DIV which receives the contents of the infowindow using jQuery
var iwOuter = $('.gm-style-iw');
// Restyle parent DIVs
var iwBackground = iwOuter.prev();
// Removes background shadow DIV
iwBackground.children(':nth-child(2)').css({'display' : 'none'});
// Removes white background DIV
iwBackground.children(':nth-child(4)').css({'display' : 'none'});
// Moves the infowindow 115px to the right.
iwOuter.parent().parent().css({left: '125px'});
// Moves the shadow of the arrow 76px to the left margin.
iwBackground.children(':nth-child(1)').attr('style', function(i,s){ return s + 'left: 26px !important;'});
// Moves the arrow 76px to the left margin.
iwBackground.children(':nth-child(3)').attr('style', function(i,s){ return s + 'left: 26px !important;'});
// Changes the desired tail shadow color.
iwBackground.children(':nth-child(3)').find('div').children().css({'box-shadow': 'rgba(72, 181, 233, 0.6) 0px 1px 6px', 'z-index' : '1'});
// Restyle child DIVs
var iwBackground = iwOuter.next();
// Set a new variable iwCloseBtn.
var iwCloseBtn = iwOuter.next();
// hide default Google Maps sprite on close tag
iwCloseBtn.children(':nth-child(1)').css({'display' : 'none'});
// Apply the desired effect to the close button
iwCloseBtn.css({
width: '45px',
height: '45px',
opacity: '1', // by default the close button has an opacity of 0.7
right: '0',
top: '0', // button repositioning
'background-image':'url(https://cdn0.iconfinder.com/data/icons/very-basic-android-l-lollipop-icon-pack/24/close-32.png)', // adding background image
'background-size': '25px',
'background-position': 'center',
'background-repeat': 'no-repeat'
});
// The API automatically applies 0.7 opacity to the button after the mouseout event.
// This function reverses this event to the desired value.
iwCloseBtn.mouseout(function(){
$(this).css({opacity: '1'});
});
});
// Create a click on the sidebar list and open the info window
$('#m'+sidebar).click(function(){
// Close info windows
$.each(map.markers, function(index,value){
if(infowindow)
infowindow.close();
});
// Click on the marker
google.maps.event.trigger(marker, "click");
});
// show info window when marker is clicked
google.maps.event.addListener(marker, 'click', function() {
infowindow.open( map, marker );
});
}
}
function center_map( map ) {
// vars
var bounds = new google.maps.LatLngBounds();
// loop through all markers and create bounds
$.each( map.markers, function( i, marker ){
var latlng = new google.maps.LatLng( marker.position.lat(), marker.position.lng() );
bounds.extend( latlng );
});
// only 1 marker?
if( map.markers.length == 1 )
{
// set center of map
map.setCenter( bounds.getCenter() );
//map.setZoom( 14 );
}
else
{
// fit to bounds
//map.fitBounds( bounds );
map.setCenter( bounds.getCenter() );
map.setZoom( 7 );
}
}
var map = null;
$(document).ready(function(){
$('.acf-map').each(function(){
// create map
map = new_map( $(this) );
});
});
})(jQuery);
You could declare a window level var actOpenWindow for store the actual open window and close before open a new one
var actInfoWindow = null;
then in your listener you shoul manage the proper situation
google.maps.event.addListener(marker, 'click', function() {
if (actInfoWindow){
actInfoWindow.close();
}
if (infowindow!==actInfoWindow){
infowindow.open( map, marker );
actInfoWindow = infowindow;
} else {
actInfoWindow.close();
actInfoWindow = null;
}
});
see https://jsfiddle.net/j10axkhc/5/ for test
Related
i have problem.. i have canvas gmaps and i added some input-text for searching mark on gmaps canvas. The problem is this "input-text for searching" located outside the gmaps canvas, how to move "input-text for searching" inside the gmaps canvas?
here is the HTML and maps.JS
HTML :
<div class="form-group ">
<input id="map-search" class="controls" type="text" placeholder="Search Box" size="50%" >
<div id="map-canvas"></div>
</div>
JavaScript :
function initialize() {
var mapOptions, map, marker, searchBox, city,
infoWindow = '',
addressEl = document.querySelector( '#map-search' ),
latEl = document.querySelector( '.latitude' ),
longEl = document.querySelector( '.longitude' ),
element = document.getElementById( 'map-canvas' );
city = document.querySelector( '.reg-input-city' );
if($('#latspan' ).val() == null){
var latCar = -6.175350;
} else {
var latCar = $('#latspan').val();
}
if($('#lngspan').val() == null){
var longCar = 106.827164;
} else {
var longCar = $('#lngspan').val();
}
mapOptions = {
// How far the maps zooms in.
zoom: 800,
// Current Lat and Long position of the pin/
center: new google.maps.LatLng( latCar, longCar ),
// center : {
// lat: -34.397,
// lng: 150.644
// },
disableDefaultUI: false, // Disables the controls like zoom control on the map if set to true
scrollWheel: true, // If set to false disables the scrolling on the map.
draggable: true, // If set to false , you cannot move the map around.
// mapTypeId: google.maps.MapTypeId.HYBRID, // If set to HYBRID its between sat and ROADMAP, Can be set to SATELLITE as well.
// maxZoom: 11, // Wont allow you to zoom more than this
// minZoom: 9 // Wont allow you to go more up.
};
/**
* Creates the map using google function google.maps.Map() by passing the id of canvas and
* mapOptions object that we just created above as its parameters.
*
*/
// Create an object map with the constructor function Map()
map = new google.maps.Map( element, mapOptions ); // Till this like of code it loads up the map.
/**
* Creates the marker on the map
*
*/
marker = new google.maps.Marker({
position: mapOptions.center,
map: map,
// icon: 'http://pngimages.net/sites/default/files/google-maps-png-image-70164.png',
draggable: true,
animation: google.maps.Animation.DROP
});
/**
* Creates a search box
*/
searchBox = new google.maps.places.SearchBox( addressEl );
/**
* When the place is changed on search box, it takes the marker to the searched location.
*/
google.maps.event.addListener( searchBox, 'places_changed', function () {
var places = searchBox.getPlaces(),
bounds = new google.maps.LatLngBounds(),
i, place, lat, long, resultArray,
addresss = places[0].formatted_address;
for( i = 0; place = places[i]; i++ ) {
bounds.extend( place.geometry.location );
marker.setPosition( place.geometry.location ); // Set marker position new.
}
map.fitBounds( bounds ); // Fit to the bound
map.setZoom( 15 ); // This function sets the zoom to 15, meaning zooms to level 15.
// console.log( map.getZoom() );
lat = marker.getPosition().lat();
long = marker.getPosition().lng();
latEl.value = lat;
longEl.value = long;
resultArray = places[0].address_components;
// Get the city and set the city input value to the one selected
for( var i = 0; i < resultArray.length; i++ ) {
if ( resultArray[ i ].types[0] && 'administrative_area_level_2' === resultArray[ i ].types[0] ) {
citi = resultArray[ i ].long_name;
city.value = citi;
}
}
// Closes the previous info window if it already exists
if ( infoWindow ) {
infoWindow.close();
}
/**
* Creates the info Window at the top of the marker
*/
infoWindow = new google.maps.InfoWindow({
content: addresss
});
infoWindow.open( map, marker );
} );
/**
* Finds the new position of the marker when the marker is dragged.
*/
google.maps.event.addListener( marker, "dragend", function ( event ) {
var lat, long, address, resultArray, citi;
console.log( 'i am dragged' );
lat = marker.getPosition().lat();
long = marker.getPosition().lng();
var geocoder = new google.maps.Geocoder();
geocoder.geocode( { latLng: marker.getPosition() }, function ( result, status ) {
if ( 'OK' === status ) { // This line can also be written like if ( status == google.maps.GeocoderStatus.OK ) {
address = result[0].formatted_address;
resultArray = result[0].address_components;
// Get the city and set the city input value to the one selected
// for( var i = 0; i < resultArray.length; i++ ) {
// if ( resultArray[ i ].types[0] && 'administrative_area_level_2' === resultArray[ i ].types[0] ) {
// citi = resultArray[ i ].long_name;
// console.log( citi );
// city.value = citi;
// }
// }
//addressEl.value = address;
latEl.value = lat;
longEl.value = long;
} else {
console.log( 'Geocode was not successful for the following reason: ' + status );
}
// Closes the previous info window if it already exists
if ( infoWindow ) {
infoWindow.close();
}
/**
* Creates the info Window at the top of the marker
*/
infoWindow = new google.maps.InfoWindow({
content: address
});
infoWindow.open( map, marker );
} );
});
}
Here is the picture on my gmaps canvas pict
thank you for being willing to read this thread, please help
Use map.controls with correct position values
var searchBox = new google.maps.places.SearchBox(document.getElementById('map-search'));
map.controls[google.maps.ControlPosition.TOP_CENTER].push(document.getElementById('map-search'));
All of my markers are coming from an AJAX call and are accurately placed on the map. However, the initial view is fully zoomed out, along the equator, in North America.
I know the solution lays somewhere with bounds.extend and map.fitBounds but apparently I'm doing it wrong.
I've always had an issue with this, so hopefully someone can help elevate this thorn in my side:
var map;
var markers = [];
var home_marker;
function initialize() {
// Display a map on the page
if ( document.contains(document.getElementById("map_canvas")) ) {
bounds = new google.maps.LatLngBounds();
map = new google.maps.Map(document.getElementById("map_canvas"), {
zoom: 12,
center: new google.maps.LatLng(48.4222, -123.3657)
});
// a new Info Window is created
infoWindow = new google.maps.InfoWindow();
// Event that closes the InfoWindow with a click on the map
google.maps.event.addListener(map, 'click', function() {
infoWindow.close();
});
// Add Home Marker
home_marker = new google.maps.Marker({
position: new google.maps.LatLng(user_address_lat, user_address_lng),
map: map,
icon: '/images/map-icon-your-home.png'
});
}
}
function displayMarkers( properties ) {
// this variable sets the map bounds and zoom level according to markers position
var bounds = new google.maps.LatLngBounds();
// For loop that runs through the info on markersData making it possible to createMarker function to create the markers
for (var i = 0; i < properties.length; i++){
var latlng = new google.maps.LatLng(properties[i]['latitude'], properties[i]['longitude']);
var price_current = properties[i]['price_current'];
var bedrooms = properties[i]['bedrooms'];
var total_baths = properties[i]['total_baths'];
var listing_id = properties[i]['listing_id'];
createMarker( latlng, price_current, bedrooms, total_baths, matrix_unique_ID );
// Marker’s Lat. and Lng. values are added to bounds variable
bounds.extend(latlng);
}
// Finally the bounds variable is used to set the map bounds
// with API’s fitBounds() function
map.fitBounds(bounds);
}
function createMarker( latlng, price, bedrooms, bathrooms, matrix_id ) {
var formatted_price = accounting.formatMoney(price, '$', 0);
var marker = new google.maps.Marker({
map: map,
position: latlng,
icon: '/images/map-icon.png'
});
google.maps.event.addListener(marker, 'click', function() {
// Variable to define the HTML content to be inserted in the infowindow
var iwContent = '<div class="row"><div class="small-12 columns"><img src="http://www.mywebsite.com/properties/'+listing_id+'/image-'+matrix_id+'-1.jpg"></div></div>' +
'<div class="row"><div class="small-12 columns"><p class="price-current text-center">'+formatted_price+'</p></div></div><hr>' +
'<div class="row"><div class="small-6 columns"><p class="bedrooms"><span class="fw-semi-bold">Beds:</span> '+bedrooms+'</p></div>' +
'<div class="small-6 columns"><p class="total-baths"><span class="fw-semi-bold">Baths:</span> '+bathrooms+'</p></div></div>';
// including content to the infowindow
infoWindow.setContent(iwContent);
// opening the infowindow in the current map and at the current marker location
infoWindow.open(map, marker);
});
}
// Sets the map on all markers in the array.
function setMapOnAll(map) {
for (var i = 0; i < markers.length; i++) {
markers[i].setMap(map);
}
}
// Removes the markers from the map, but keeps them in the array.
function clearMarkers() {
setMapOnAll(null);
}
// Deletes all markers in the array by removing references to them.
function deleteMarkers() {
clearMarkers();
markers = [];
}
Make a new Part to your script or make a new one, and code it specificly to change zoom in camera ammount and, add ui button for it.
I am building a Google Maps based web app on which I plot a moving dot of the user location. I am fetching continuously the user location from a server and would like to use the current user location when loading the map to center the window around it, meaning, when the user loads the site, the map will be centered around the first lat/long fetched from the server but enable the user to pan the map afterwards without re-centering it around where the user is. I was able to keep the map centered constantly around the user location but can't figure out how to use the first fetched location to center the map during initialization. My code is below, any help would be greatly appreciated. Thanks!
<script>
var locations = [
['location a', 37.771678, -122.469357],
['location b', 37.768557, -122.438458],
['location c', 37.755121, -122.438973],
['location d', 37.786127, -122.433223]
];
var map;
var i;
var marker;
var google_lat = 37.722066;
var google_long = -122.478541;
var myLatlng = new google.maps.LatLng(google_lat, google_long);
var image_dot = new google.maps.MarkerImage(
'images/red_dot.png',
null, // size
null, // origin
new google.maps.Point( 8, 8 ), // anchor (move to center of marker)
new google.maps.Size( 8, 8 ) // scaled size (required for Retina display icon)
);
function initialize() {
var mapOptions = {
zoom: 12,
center: myLatlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
setMarkers(map, locations);
} //initialize();
function setMarkers(map, locations) {
for (var i = 0; i < locations.length; i++) {
var beach = locations[i];
var myLatLng1 = new google.maps.LatLng(beach[1], beach[2]);
marker = new google.maps.Marker({
position: myLatLng1,
icon: image_dot,
map: map
});
}
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
<script type="text/javascript">
var Tdata;
var image = new google.maps.MarkerImage(
'images/bluedot_retina.png',
null, // size
null, // origin
new google.maps.Point( 8, 8 ), // anchor (move to center of marker)
new google.maps.Size( 17, 17 ) // scaled size (required for Retina display icon)
);
var userMarker = new google.maps.Marker({icon: image});
$.ajax({
method : "GET",
url: "get_location.php",
success : function(data){
Tdata=JSON.parse(data);
myFunction();
}
});
function myFunction(){
var interval = setInterval(function() {
$.get("get_location.php", function(Tdata) {
var JsonObject= JSON.parse(Tdata);
google_lat = JsonObject.lat;
google_long = JsonObject.long;
myLatlng = new google.maps.LatLng(google_lat, google_long);
userMarker.setPosition(myLatlng);
userMarker.setMap(map);
//map.setCenter(myLatlng); --> this is not what I want since it will always keep the map centerd around the user
});
}, 1000);
}
</script>
Only set the map center the first time. One way of detecting the first time would be to create the "userMarker" the first time the data is loaded.
var userMarker;
$.ajax({
method : "GET",
url: "get_location.php",
success : function(data){
Tdata=JSON.parse(data);
myFunction();
}
});
function myFunction(){
var interval = setInterval(function() {
$.get("get_location.php", function(Tdata) {
var JsonObject= JSON.parse(Tdata);
google_lat = JsonObject.lat;
google_long = JsonObject.long;
myLatlng = new google.maps.LatLng(google_lat, google_long);
if (!userMarker || !userMarker.setPosition) {
// create the marker
userMarker = new google.maps.Marker({
icon: image,
position: myLatlng,
map:map
});
// center the map the first time, when the marker is created
map.setCenter(myLatlng);
} else { // marker aleady exists
userMarker.setPosition(myLatlng);
}
});
}, 1000);
}
proof of concept fiddle
I've looked at all the suggestions from previously asked questions similar to mine, as well as following the google maps api developers info page on overlays, but no answers have helped - I'm trying to simply change the color of the markers from the standard to green, but every time I try and add fillColor, etc. to my code it either won't show the marker or won't show the map at all. Anyone have any idea what I'm doing wrong?
function createMap() {
// map options
var options = {
zoom: 4,
center: new google.maps.LatLng(39.909736, -98.522109), // centered US
mapTypeId: google.maps.MapTypeId.ROADMAP,
mapTypeControl: false
};
// init map
map = new google.maps.Map(document.getElementById('map_canvas'), options);
}
function addMarker() {
fetchNewQuote();
var indext;
for (indext = 0; indext <array.length; ++indext) {
splitarr = array[indext].split(":");
geosplit = splitarr[1].split(", ");
if (indext < 50) {
$('#tweet_table').append(array[indext] + "</br></br>");
}
var marker = new google.maps.Marker({
position: new google.maps.LatLng(geosplit[0], geosplit[1]),
map: map,
title: 'Click me to see what this individual tweeted!'
});
(function(marker, splitarr, indext) {
var tweetclick = "TOBACCO VISUALIZATION</br>" + "Keyword: " + splitarr[0] + "</br> Coordinates: " + splitarr[1] + "</br> Tweet: " + splitarr[2];
google.maps.event.addListener(marker, 'click', function() {
infowindow = new google.maps.InfoWindow({
content: tweetclick
});
infowindow.open(map, marker);
});
})(marker, splitarr, indext);
marker.setMap(map);
markersArray.push(marker);
}
}
You can load your own marker like this :
var icon = https://chart.googleapis.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|00FF00
You have to pass the color of the marker at RGB format after the pipe. If you want a blue marker, just pass 0000FF instead of 00FF00.
Then, use it like this :
var marker = new google.maps.Marker({
position: new google.maps.LatLng(geosplit[0], geosplit[1]),
map: map,
title: 'Click me to see what this individual tweeted!'
icon: icon
});
Hope this helps !
I have a map that has checkboxes for users to select what they would like displayed on the map. Everything works well with the exception of the following two items.
When a user selects an item from the list the marker does display on the map, however the map does not re-center on the marker. This is needed for a marker that is outside the viewable area of the map when the page loads.
When I have multiple markers open on the map I would like to have only 1 infowindow open at a time, currently if I click on 10 markers there will be 10 infowindows open. I would like to have it where if an infowindow is open and another marker is clicked then the first infowindow closes.
I have pasted a snippet of the code for one of the markers below, any help would be greatly appreciated!
jQuery(document).ready(function(){
/**
* The Map object.
* #type {google.maps.Map}
*/
var mapOptions = {
center: new google.maps.LatLng(36.812946,-119.746953),
zoom: 16,
mapTypeId: google.maps.MapTypeId.SATELLITE
};
var map = new google.maps.Map(document.getElementById("map"), mapOptions);
/**
* The markers array.
* #type {Object}
*/
var markers = {};
markers.building37 = [];
var marker0237 = new google.maps.Marker({
visible: false,
icon: new google.maps.MarkerImage("images/website/brown_Marker.png",new google.maps.Size(32,37),null,null),
title: 'Building',
position: new google.maps.LatLng(36.80694607313768,-119.73590791225433),
center: position,
map: map
});
markers.building37.push(marker0237);
var info_window0237 = new google.maps.InfoWindow({
content: '<div id="infobubble"><div id="img"><img src="images/buildings/Foundation001.jpg" alt="Foundation Building"></div><div id="desc"><h3>Foundation</h3></div></div>',
maxWidth:350,
});
google.maps.event.addListener(marker0237, "click", function() {
info_window0237.open(map,marker0237);
});
var showBuilding37 = false;
var mgrBuilding37 = null;
/**
* Toggles Building 37 Marker Group visibility.
*/
function toggleBuilding37()
{
showBuilding37 = !showBuilding37;
if (showBuilding37)
for (var i=0; i < markers.building37.length; i++)
markers.building37[i].setVisible(true);
if (mgrBuilding37)
{
if (showBuilding37)
{
mgrBuilding37.addMarkers(markers.building37, 0);
mgrBuilding37.refresh();
}
else
{
mgrBuilding37.clearMarkers();
mgrBuilding37.refresh();
}
}
else
{
mgrBuilding37 = new MarkerManager(map, {trackMarkers: true, maxZoom: 15});
google.maps.event.addListener(mgrBuilding37, "loaded", function() {
if (showBuilding37)
{
mgrBuilding37.addMarkers(markers.building37, 0);
mgrBuilding37.refresh();
}
else
{
mgrBuilding37.clearMarkers();
mgrBuilding37.refresh();
}
});
}
}
google.maps.event.addDomListener(
document.getElementById("building37-cb"),"click", toggleBuilding37);
});
I don't see where you are setting the map center.
You should do something like map.setCenter(location); when you add a marker.
You should keep a list of info windows and when you display one, loop through the others and hide their info windows.
//Declare your info window array
var infoWindows = new Array();
var info_window0237 = new google.maps.InfoWindow({
content: '<div id="infobubble"><div id="img"><img src="images/buildings/Foundation001.jpg" alt="Foundation Building"></div><div id="desc"><h3>Foundation</h3></div></div>',
maxWidth:350,
});
//After you make an infowindow, add it to the array
infoWindows.push(info_window0237);
google.maps.event.addListener(marker0237, "click", function() {
//When you show an infowindow on click, hide the rest
for(i = 0; i < indowWindows.length; i++)
{
//this will close all the infowindows you added to the array
infoWindows[i].close();
}
info_window0237.open(map,marker0237);
});