Learn the technique for showcasing numerous markers on Google Maps, each equipped with its own individualized info windows

https://i.sstatic.net/1tTUD.png

// map center
var center = new google.maps.LatLng(2.855262784366583, 105.4302978515625);

function initialize() {
var mapOptions = {
center: center,
zoom: 7,
mapTypeId: google.maps.MapTypeId.ROADMAP

};

// Create a <script> tag and set the USGS URL as the source.
var script = document.createElement('script');
script.src = 'https://developers.google.com/maps/documentation/javascript/examples/json/earthquake_GeoJSONP.js';
document.getElementsByTagName('head')[0].appendChild(script);
var map = new google.maps.Map(document.getElementById("map-canvas"),mapOptions);

window.eqfeed_callback = function(results) {
for (var i = 0; i < results.features.length; i++) {
var coords = results.features[i].geometry.coordinates;
var latLng = new google.maps.LatLng(coords[1],coords[0]);
var marker = new google.maps.Marker({
position: latLng,
map: map
});



var content = '<div id="iw-container">' +
'<div class="iw-title">Porcelain Factory of Vista Alegre</div>' +
'<div class="iw-content">' +
'<div class="iw-subTitle">History</div>' +
'<img src="http://maps.marnoto.com/en/5wayscustomizeinfowindow/images/vistalegre.jpg" alt="Porcelain Factory of Vista Alegre" height="115" width="83">' +
'<p>Founded in 1824, the Porcelain Factory of Vista Alegre was the first industrial unit dedicated to porcelain production in Portugal. For the foundation and success of this risky industrial development was crucial the spirit of persistence of its founder, José Ferreira Pinto Basto. Leading figure in Portuguese society of the nineteenth century farm owner, daring dealer, wisely incorporated the liberal ideas of the century, having become "the first example of free enterprise" in Portugal.</p>' +
'<div class="iw-subTitle">Contacts</div>' +
'<p>VISTA ALEGRE ATLANTIS, SA<br>3830-292 Ílhavo - Portugal<br>'+
"<br>Phone. +351 234 320 600<br>e-mail: <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail='b2d5d7c0d3def2c4d3d39cc2c6'>[email protected]</a><br>www: www.myvistaalegre.com</p>"+
'</div>' +
'<div class="iw-bottom-gradient"></div>' +
'</div>';

var infowindow = new google.maps.InfoWindow({
content: content,
maxWidth: 350
});

var marker = new google.maps.Marker({
position: latLng,
map: map,
title:"Porcelain Factory of Vista Alegre"
});


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

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

google.maps.event.addListener(infowindow, 'domready', function() {

var iwOuter = $('.gm-style-iw');

var iwBackground = iwOuter.prev();

iwBackground.children(':nth-child(2)').css({'display' : 'none'});
iwBackground.children(':nth-child(4)').css({'display' : 'none'});
iwOuter.parent().parent().css({left: '115px'});
iwBackground.children(':nth-child(1)').attr('style', function(i,s){ return s + 'left: 76px !important;'});
iwBackground.children(':nth-child(3)').attr('style', function(i,s){ return s + 'left: 76px !important;'});
iwBackground.children(':nth-child(3)').find('div').children().css({'box-shadow': 'rgba(72, 181, 233, 0.6) 0px 1px 6px', 'z-index' : '1'});

var iwCloseBtn = iwOuter.next();

iwCloseBtn.css({opacity: '1', right: '38px', top: '3px', border: '7px solid #48b5e9', 'border-radius': '13px', 'box-shadow': '0 0 5px #3990B9'});

if($('.iw-content').height() < 140){
$('.iw-bottom-gradient').css({display: 'none'});
}

iwCloseBtn.mouseout(function(){
$(this).css({opacity: '1'});
});
});
}
}


google.maps.event.addDomListener(window, 'load', initialize);
#map-canvas {
margin: 0;
padding: 0;
height: 400px;
max-width: none;
}
#map-canvas img {
max-width: none !important;
}
.gm-style-iw {
width: 350px !important;
top: 15px !important;
left: 0px !important;
background-color: #fff;
box-shadow: 0 1px 6px rgba(178, 178, 178, 0.6);
border: 1px solid rgba(72, 181, 233, 0.6);
border-radius: 2px 2px 10px 10px;
}
#iw-container {
margin-bottom: 10px;
}
#iw-container .iw-title {
font-family: 'Open Sans Condensed', sans-serif;
font-size: 22px;
font-weight: 400;
padding: 10px;
background-color: #48b5e9;
color: white;
margin: 0;
border-radius: 2px 2px 0 0;
}
#iw-container .iw-content {
font-size: 13px;
line-height: 18px;
font-weight: 400;
margin-right: 1px;
padding: 15px 5px 20px 15px;
max-height: 140px;
overflow-y: auto;
overflow-x: hidden;
}
.iw-content img {
float: right;
margin: 0 5px 5px 10px;
}
.iw-subTitle {
font-size: 16px;
font-weight: 700;
padding: 5px 0;
}
.iw-bottom-gradient {
position: absolute;
width: 326px;
height: 25px;
bottom: 10px;
right: 18px;
background: linear-gradient(to bottom, rgba(255,255,255,0) 0%, rgba(255,255,255,1) 100%);
background: -webkit-linear-gradient(top, rgba(255,255,255,0) 0%, rgba(255,255,255,1) 100%);
background: -moz-linear-gradient(top, rgba(255,255,255,0) 0%, rgba(255,255,255,1) 100%);
background: -ms-linear-gradient(top, rgba(255,255,255,0) 0%, rgba(255,255,255,1) 100%);
}
<!DOCTYPE html>
<html lang="en" >

<head>
<meta charset="UTF-8">
<title>5 ways to customize the Google Maps infowindow</title>;

<link rel="stylesheet" href="css/style.css">

</head>

<body>

  <div id="map-canvas"/>
</body>
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap">
</script>
<script src='http://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.2/jquery.min.js'></script>
<script  src="js/index.js"></script>

</body>

</html>

Answer №1

Here's a simple solution to improve your code:

 // This event expects a click on a marker
 // When this event is fired the Info Window is opened.
 google.maps.event.addListener(marker, 'click', function() {
   infowindow.open(map,marker);
 });

Update it to:

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

In this updated version, using this refers directly to the clicked marker, ensuring that the InfoWindow opens on the correct marker. However, if all InfoWindows have the same content, this may limit its functionality.

Check out this proof of concept fiddle

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Having trouble linking a sqlite file in your tauri + vue project?

After successfully installing tauri-plugin-sql by adding the specified content to src-tauri/Cargo.toml : [dependencies.tauri-plugin-sql] git = "https://github.com/tauri-apps/plugins-workspace" branch = "v1" features = ["sqlite" ...

Tips on changing font color within an email body in Outlook using a C#.NET Windows application

While working on a c#.net windows application, I encountered an issue with setting font color for specific lines in the email body when sending mail to Outlook. Despite trying various methods, I was unable to find a solution. Below is a snippet of my code: ...

Is there a way for me to discover the top trending photos on Instagram today?

Finding information on the Instagram API can be quite challenging due to poor documentation. Is there a method available to discover the most liked Instagram photos by location, such as identifying the top picture liked by Danish users today? Any insight ...

Having trouble getting typeahead suggestions to display in Bootstrap UI when using AngularJS?

I am having trouble getting static suggestions to display in a search textbox. I have tried following the example at this link. Below is the code I am working with: Here is my HTML code: <div> <input type="text" name="questions" id="que ...

Failure to authorize Google Maps API

Having trouble connecting to the Google MAP API with a persistent error: Authorization failure. Please see https://developers.google.com/maps/documentation/android/start for instructions on properly setting up the map. Make sure that the following match ...

How can you calculate the ratio of one property value to another in AngularJS?

In my code, I am using ng-repeat to display data values from an object. <div ng-controller="myctrl"> <ul ng-repeat="number in numbers"> <li><span ng-bind="number.first"></span></li> <li><span ng-bind ...

The contenteditable attribute does not function properly in a foreignobject element on Firefox browsers

<?xml version="1.0" standalone="yes" ?> <svg xmlns="http://www.w3.org/2000/svg"> <foreignObject width="100" height="100" x="20" y="65"> <body xmlns="http://www.w3.org/1999/xhtml"> <p contenteditable="true">text&l ...

Using Selenium IDE to click on a checkbox within a table row

Currently, I am utilizing Selenium IDE to navigate through a table with multiple rows and columns. Each row within the table contains its own checkbox for selection purposes. In my attempt to search for a specific row, I have been using the following comm ...

Attempting to upload an item using ThreeJs

Can someone assist me with loading an object file from my local browser in Threejs ( Rev 71)? I keep encountering an error that says loadModel.html:1 Uncaught SyntaxError: Unexpected token #. Even after trying to load the object file using chrome --allow- ...

Learn how to smoothly transfer a URL from JavaScript to HTML and initiate the download process

I created a website that solely relies on HTML5, CSS and JavaScript to function. The core functionality of this website involves utilizing YouTube URLs. I have stored the URL of a specific YouTube video as a variable, now I am looking for a way to transfer ...

Can we find a solution to optimize "Crystal Reports" for mobile browsers and make it responsive?

I'm in the process of making my entire Asp.net application responsive for mobile browsers by utilizing Bootstrap. However, I've encountered a challenge with making Crystal Report responsive for mobile browsers. If anyone has any advice on how to ...

Tips for wrapping text around an image using Bootstrap 5

I am having trouble getting my text to wrap around an image using the Bootstrap 5 grid system. I've attempted to use 'float: right' on the image, but it hasn't produced the desired result. The text should flow naturally around the imag ...

Submitting forms from a different router in React can pose a unique challenge

As a beginner in React, I am working on creating a simple meal app. In my App component, I am fetching meal data from an api and allowing users to click on a meal for more details. However, I am facing an issue where searching for a new meal on the detail ...

Unveiling the Masked Phone Number in jquery.maskedinput for Database Insertion

Currently, I am grappling with removing the phone number mask while working with jquery.maskedinput.min.js in an MVC web app. Here is the JavaScript code snippet I am using: @section Scripts { @Scripts.Render("~/bundles/jqueryval") <script type="text/ ...

Fix a typing issue with TypeScript on a coding assistant

I'm struggling with typing a helper function. I need to replace null values in an object with empty strings while preserving the key-value relationships in typescript // from { name: string | undefined url: string | null | undefined icon: ...

Tips for minimizing the arrow size in the infowindow on a Google Maps interface

As a newcomer to customizing Google Maps, I am looking to decrease the size of the arrow in the infowindow and position it in the bottom left corner for a better appearance. I am struggling to figure out how to adjust the height and width of the arrow and ...

capture the mouse click event on a particular object within the renderer

I have set up a canvas renderer with two mesh (cubes) and I am trying to capture the click event on each cube in order to execute the appropriate method for it. Currently, I am able to capture the click event on the entire renderer, so when I click on cub ...

Reducing the width of the bootstrap table does not seem to work properly when trying

I am currently working on a bootstrap table design that features a table with a rowspan of "2" in the right corner, creating a layout with 2 rows on one end and another rowspan of "2" on the other end, as shown in the following image: https://i.sstatic.net ...

What is the method for assigning a maximum value of 300 to a bootstrap progress bar?

I'm in the process of creating a progress bar with a maximum value of 300, but I'm struggling to set it at 300. It currently works for a maximum value of 100, but I want it to be 300. Here's what I've attempted: <div class="mt-3 pr ...

Learning to retrieve specific properties from an event target in JavaScript

Here is the code snippet I am working with: <h1 msgId = "someId"> Some text </h1> And in my code.js file, I have the following function: document.addEventListener('click', function(e) { target = e.target; }, false); I am tryin ...