Is there a way to invoke a method on an object stored in an array index?

Attempting to generate infowindows for markers within a Google Map, I utilized an array to create "disposable objects" within a for loop. Unfortunately, my approach is not yielding the desired results. Clicking on the markers has no effect, and upon checking the console, I encounter the following error message:

Uncaught TypeError: Cannot call method 'open' of undefined 

Not assigning the object to an array index causes each marker click to only open the last info window (as the object being overwritten updates all references to previous objects).

How can I resolve this issue?

markers = []
infowindows = []
counter = 0
for location in exports.response.locations
    myLatlng = new google.maps.LatLng(location.latitude, location.longitude);
    markers[counter] = new google.maps.Marker(
        position: myLatlng
        map: map
        title: location.name
    )
    contentString = '<div id="info_content_' + location.id + '">' + '<h3>' + location.name + '</h3>' + '<ul>' + '<li>' + location.address + ', ' + location.city + '</li>' + '</ul>'
    infowindows[counter] = new google.maps.InfoWindow(content: contentString)

    google.maps.event.addListener markers[counter], "click", ->
        infowindows[counter].open(map, markers[counter])

    counter++

Note

The issue lies in the 3rd to last line of the code above (

infowindows[counter].open(map, markers[counter])
)

Answer

While every response to this question contributed to finding a solution, I ultimately resolved it using a forEach loop:

markers = []
infowindows = []
exports.response.locations.forEach (location) ->
    myLatlng = new google.maps.LatLng(location.latitude, location.longitude);
    markers[location.id] = new google.maps.Marker(
        position: myLatlng
        map: map
        title: location.name
    )
    contentString = '<div id="info_content_' + location.id + '">' + '<h3>' + location.name + '</h3>' + '<ul>' + '<li>' + location.address + ', ' + location.city + '</li>' + '</ul>'
    infowindows[location.id] = new google.maps.InfoWindow(content: contentString)

    google.maps.event.addListener markers[location.id], "click", ->
        infowindows[location.id].open(map, markers[location.id])

Answer №1

It seems like the issue you're encountering is with the counter variable losing its valid index:

for location in exports.response.locations

    google.maps.event.addListener markers[counter], "click", ->
        infowindows[counter].open(map, markers[counter])

    counter++

The problem lies in the fact that counter is being captured in the onClick handler closure.

This means that the value of counter will increment beyond its bounds before the onClick handler is executed.

As a result, all of the handlers will use the same value for counter.

Answer №2

When using addListener, keep in mind that it triggers code asynchronously. This means that the value of the counter may not be the same when the callback function is executed as it was when the function was initially declared. To ensure that the variables retain their original values, it's important to enclose them in a closure. The code snippet below demonstrates a reliable method for achieving this. While declaring currentCounter within the loop should suffice, explicitly using a closure can provide additional clarity.

markers = []
infowindows = []
counter = 0

for location in exports.response.locations
    myLatlng = new google.maps.LatLng(location.latitude, location.longitude);
    markers[counter] = new google.maps.Marker(
        position: myLatlng
        map: map
        title: location.name
    )
    
    contentString = '<div id="info_content_' + location.id + '">' + '<h3>' + location.name + '</h3>' + '<ul>' + '<li>' + location.address + ', ' + location.city + '</li>' + '</ul>'

    infowindows[counter] = new google.maps.InfoWindow(content: contentString)
    
    google.maps.event.addListener markers[counter], "click", (function(infowindows, markers, currentCounter) { 
        return function() {  infowindows[currentCounter].open(map, markers[currentCounter]) }
    })(infowindows, markers, counter)
    
    counter++    

For more examples and insights on using closures within loops, refer to JavaScript closure inside loops – simple practical example

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

Is there a way to trigger the activation of the datepicker during the `onLoad` event?

For my project, I am utilizing this datepicker. While I am familiar with using scripts to handle changes in the date value, I am unsure of how to implement it on page load. $('.date_set .date').datepicker({ startView : 0, ...

Sending data using Ajax to the server-side code in ASP.NET

Struggling to successfully pass a series of values through Ajax to a code-behind method in order to insert the data into a database table. However, encountering issues where string variables are being received as empty strings and int variables as 0. The ...

Sharing golang gin session with next.js

Utilizing the latest version of Next.js v14.2.3 and App Router. I am currently implementing cookie-based sessions from the gin-contrib documentation, in order to increase a session count. // Backend Golang code snippet ... cookieStore := sessi ...

AngularJS interprets expressions in the 'action' attribute

This afternoon I encountered a rather peculiar behavior with AngularJS. If "//" is present in an expression within the "action" attribute of a form, Angular will throw an interpolate error. Take a look at the code snippet below. When you run this code, t ...

Validating a request model against the schema defined in an OpenAPI 3 (Swagger) specification in NodeJS: A comprehensive guide

I am searching for a tool or framework that can validate the model of incoming requests against a schema defined in the Swagger documentation. ...

Node.js and Azure blob storage compliment each other perfectly

After utilizing Azure DB for some time, I encountered an issue where I couldn't store large files in Azure. As a workaround, I discovered Storage Account. I have been using tedious (JS) to make queries. Is it possible to save and retrieve data using ...

"Learn how to update an existing table row and populate its cells with JSON data retrieved from a successful AJAX request without creating a

Currently, I am utilizing CouchCMS. The platform offers a feature known as repeatable regions which essentially generates tables to showcase recurring content. The defined repeatable region looks like this: <cms:repeatable name="item_detail" ...

Save the value of a webpage element into a variable and utilize it across multiple JavaScript files in TestCafe

We are working in the insurance domain and have a specific scenario that we want to achieve using TestCafe: 1st step: Login into the application 2nd step: Create a claim and store the claim number in a global variable 3rd step: Use the globally declared c ...

Looking for assistance with navigating through this URL using Python (requests, beautifulsoup, or selenium) or Javascript (node js, puppeteer)?

While attempting to gather data, I encountered an interesting pagination challenge on the following URL: My expertise in Web Scraping was put to the test as this website implemented a unique JavaScript-driven pagination. For the initial 5 pages, it simply ...

Is it time to advance to the next input field when reaching the maxLength?

In my Vue form, I have designed a combined input field for entering a phone number for styling purposes. The issue I am facing is that the user needs to press the tab key to move to the next input field of the phone number. Is there a way to automaticall ...

How can I link two separate webpages upon submitting a form with a single click?

Here is a snippet of my code: <form action="register.php" method="post"> <input type="text" name="uname"> <input type="submit" > </form> Within the register.php file, there are codes for connecting to a database. I am looking ...

Step-by-step guide on dynamically adding "Input Tags" to the DOM at runtime using Selenium's JavascriptExecutor

In order to dynamically add the following element to the DOM during run time, I need assistance... <input type="text" name="imagesToAdd" value="3566"> My initial attempt was to use Selenium JavascriptExecutor for this task. However, I encounter ...

How to use jQuery to highlight the parent element when clicking on a child element?

I'm struggling with some HTML code that looks like the following: <ul> <li class="curent"><a href="home.html">Home</a></li> <li> <a href="javascript:void(0)">Products</a> <ul ...

The canvas game's animation can only be activated one time

I am currently working on designing a straightforward canvas game: Here is the code snippet located on CodePen var canvas; var ctx; var x = 300; var y = 400; var r = 0; var mx = 0; var my = 0; var WIDTH = 600; var HEIGHT = 400; function circle(x,y,r) ...

basic computation of whole and decimal values using jquery

I'm having trouble multiplying 2 values in my code where the quantity is an integer and credit price is a decimal number. However, when I run the script, nothing seems to happen. Can someone please help me identify and resolve this issue? Any insight ...

I was disappointed by the lackluster performance of the DataTable in CodeIgniter; it did not

I recently started using CodeIgniter and I'm having trouble getting the dataTable to work. Here's a snippet of my page: <table class="table table-striped table-bordered table-hover dataTables_default" id="dataTables-example"> ...

How can you choose multiple options in a Select2 dropdown when it first loads?

I'm having trouble correctly loading a JSON array of selected items into an existing select2 dropdown. I want certain items to be pre-selected when the page loads, but I'm struggling with the syntax. Consider the following JSON array, stored in ...

Problem with jQuery's .prepend method being called twice on list items

Looking to enhance the appearance of a list by adding some icons before the anchor links within each list item. <ul class="submenu-children"> <li><a href="#">Link</a></li> <li><a href="#">Link</a></li> ...

Extracting Querystring Value in C#

When using the code below to set the iframe src with JavaScript, everything works as expected. However, in the C# code behind, I am receiving the query string in a format like this: id=Y&amp%3bcust_id=100&amp%3. Is there a way to simplify this? v ...

Stop jQuery popups from wrapping text when resizing the browser window

Whenever a link is clicked, a jQuery popup appears. The popup functions properly in terms of opening and closing, but I would like to ensure that its position remains fixed when resizing the browser window to avoid any wrapping issues. Typically, I use a ...