Challenges with Scope in Using AJAX Calls within an Infowindow

Could it be a scope issue? Feel free to correct me if I'm mistaken.

I've got a for loop that's placing markers on my map. Each marker has a different infowindow that loads content using ajax callbacks.

This is a simplified version of the script with the problem highlighted:

var xhr = "";
var infowindow = new google.maps.InfoWindow();
var marker, i;
var polylineCoordinates = [new google.maps.LatLng(78.782762, 17.917843),
                           new google.maps.LatLng(-0.829439, -91.112473),
                           new google.maps.LatLng(15.066156, -23.621399),
                          ]


function createHttpRequest() {
    try {   
        xhr = new XMLHttpRequest();
        return xhr;
        }
        catch (e)
        {
            //assuming IE6
            try {
            xhr = new activeXBbject("microsoft.XMLHTTP");
            return xhr;
            }
            catch (e)   {
                return alert("Unable to create an XMLHttpRequest object");
            }
        }
}



function initialize() {

    var mapOptions = {
      center: new google.maps.LatLng(78.782762,17.917843),
      zoom: 10,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    };
        map = new google.maps.Map(document.getElementById("map_canvas"),
        mapOptions);
}

for (i = 0; i < polylineCoordinates.length; i++) {
    marker = new google.maps.Marker({
        position: polylineCoordinates[i],
        map: map
    });

    google.maps.event.addListener(marker, 'click', (function (marker, i) {
        return function () {
            infowindow.setContent("<div id=\"infowindow\">" + getStationInfo(infoWindowDiv) + "</div>");
            infowindow.open(map, marker);

        }
    })(marker, i));

} 

function infoWindowDiv(stationInfo) {
    var add = document.createTextNode(stationInfo);
    document.getElementById("infowindow").appendChild(add);
}


function getStationInfo(callback) {
    var xhr = createHttpRequest();
    var url = "stations.php" 
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4 && xhr.status == 200) {
            var stationInfo = "This is a Test";
            return callback(stationInfo)
        } 

    } 
    xhr.open("GET", url, true);
    xhr.send(null);
} 

Small Edit: Functions have been moved outside of the loop

Edit 2: The ajax call isn't the issue, the URL was changed just for the code sample. The final output displays "This is a test" in the infowindow, indicating a successful callback. Additionally, note there is no responseText or responseXml involved. The returned variable is not related to the URL

The callback seems to be working fine, but there's an unwanted 'undefined' displayed above it.
The console doesn't show any errors.
Output:

undefined
This is a test

If it's functioning, why does it display as undefined?

Answer №1

Here is what's going on:

  1. When you click on the infowindow,
  2. The function getStationInfo(infoWindowDiv) is triggered, sending an AJAX request that doesn't return any useful information (it's "undefined" due to the lack of a return statement),
  3. An error will occur in the AJAX function because the URL specified as "Unnecessary at this point" won't trigger the onreadystatechange function. However, you mentioned that this isn't a problem.
  4. A JavaScript error
    Uncaught TypeError: Cannot call method 'appendChild' of null
    happens because the div with the id infowindow hasn't been added to the DOM yet.

To address this, consider adding an event listener to the infowindow so it waits for the rendering process (domready) before trying to access the div with id="infowindow."

Corrected code snippet:

var xhr = "";
var infowindow = new google.maps.InfoWindow();
var map = null;
var marker, i;
var polylineCoordinates = [new google.maps.LatLng(78.782762, 17.917843),
                           new google.maps.LatLng(-0.829439, -91.112473),
                           new google.maps.LatLng(15.066156, -23.621399)
                          ];

function initialize() {
    var mapOptions = {
        center: new google.maps.LatLng(78.782762, 17.917843),
        zoom: 10,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };

    map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);

    for (i = 0; i < polylineCoordinates.length; i++) {
        marker = new google.maps.Marker({
            position: polylineCoordinates[i],
            map: map
        });

        google.maps.event.addListener(marker, 'click', (function (marker, i) {
            return function () {
                infowindow.setContent("<div id=\"infowindow\" style=\"height:50px;width:200px;\"></div>");
                infowindow.open(map, marker);
                google.maps.event.addListenerOnce(infowindow,"domready", function(){
                    getStationInfo(infoWindowDiv);
                });
            })(marker, i));
    } // End loop to add markers
}

function infoWindowDiv(stationInfo) {
    var add = document.createTextNode(stationInfo);
    document.getElementById("infowindow").appendChild(add);
}

function getStationInfo(callback) {
    var stationInfo = "This is a Test";
    callback(stationInfo);
} // End of getStationInfo

google.maps.event.addDomListener(window, 'load', initialize);

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

Invoking Javascript Functions using their names

Suppose I have the following element on my page... <span data-function="DoSomething">Click</span> ... and then add the following to my page header... $(document).ready(function() { $('[data-function]').each(function() { ...

Pause the jquery script when a key is pressed

Currently, I have a script that loads a php file within a div and automatically refreshes every 5 seconds. Check out the code below: $("#load_timeout").load("time_out.php"); var refreshId = setInterval(function() { $("#load_timeout").load('time_o ...

Moving the layout container towards the left: a quick guide

I am currently attempting to display the legend contents in a horizontal alignment within the layout container. The issue is that while the layout containing the legend aligns horizontally as desired, it extends beyond the screen border. I do not want the ...

Ways to apply the .not selector efficiently in jQuery

I have a situation with two separate divs, one named task1 and the other named task2. Each of these tasks contains panels with various names. Within task2, there is a duplicate name (Greg), who also belongs to the duplicate class. I'm trying to figure ...

Setting up a new folder in the internal storage within a React Native Expo environment

In my React Native Expo project, I am utilizing two functions to store data in a JSON file and then save the file to internal storage. However, the code currently asks for permission to store inside a chosen folder, but does not create the "ProjectName" fo ...

Having issues with $emitting not working for parent-child components in Vue. Any ideas on what I might be doing incorrectly?

I have a login component that I need to call in the main vue component of App.vue. Within the login vue, when I click on any button, it should activate another vue component using Vue.js router to replace the login page. I have searched for solutions but h ...

Manual mocking in Jest is only effective for the initial function call

In my project, I have created a custom XHR wrapper in utils/xhr.js and I am using Jest manual mocking feature to mock it. However, I am running into an issue where only the first XHR call is being tracked: utils/xhr.js let xhr = { get: function(par ...

Activate fancybox after the AJAX content has finished loading

I have a <div> element with the id <div id="displayinformation"> where I am loading content dynamically using Ajax. Some of the loaded content contains links, and I want to display them in a Fancybox lightbox. I have confirmed that the Fancyb ...

Exploring the functionality of className using materialUI

Attempting to test whether my component has a specific class is proving challenging. This difficulty stems from the fact that the class is generated using MaterialUI. For instance, I am looking for a class named spinningIconCenter, but in reality, it appea ...

The order of items in MongoDB can be maintained when using the $in operator by integrating Async

It's common knowledge that using {$in: {_id: []}} in MongoDB doesn't maintain order. To address this issue, I am considering utilizing Async.js. Let's consider an example: const ids = [3,1,2]; // Initial ids retrieved from aggregation con ...

Utilize the power of REACT JS to transform a specific segment within a paragraph into a hyperlink. Take advantage of the click event on that hyperlink to execute an API request prior to

In React JSX, I'm encountering an issue trying to dynamically convert a section of text into an anchor tag. Additionally, upon clicking the anchor tag, I need to make an API call before redirecting it to the requested page. Despite my attempts, I have ...

JavaScript for validating dimension text input has unique functionalities

I am looking for guidance on validating an ASP textbox using JavaScript. My goal is to validate a user's input in the format of 4-1/2, 80-1/2, 6/8, or simply 5. Only these types of patterns should be allowed, and each input must contain only one numbe ...

Sinon Stub generates varying values with each invocation

I'm pretty new to TypeScript and JavaScript, but I've managed to create a functioning VScode extension that I'm really happy with. However, I'm running into some issues with my Mocha tests. Here's a snippet of the code I'm str ...

Is it possible to programmatically hide the Textarea and submit button for each row in a PHP-generated database table?

After spending a considerable amount of time on this project, I'm looking to incorporate a JavaScript effect (hide/unhide) into a basic submit form. Although the functionality is successful, it seems to be limited to only one row in the database tabl ...

Image transformed by hovering effect

I've been attempting to add a hover effect to the images in my WordPress theme. The images are displayed in a grid format, created by the featured image on the posts. The grid layout is controlled within content.php <?php /** * controls main gri ...

The "scrollTop" function seems to be malfunctioning in Firefox but works perfectly fine in Chrome. Is there a way to fix this issue?

Issue with scrollTop in Firefox jQuery(window).scroll(function(){ var NextScroll = jQuery(this).scrollTop(); if (NextScroll >= 800){ jQuery('#logomacchia').addClass("maccancello"); } else { jQuery('#logomacch ...

Text that changes within a set-sized box

I'm working with a fixed-size div that contains dynamically generated text. Is there an easy method using DOJO or plain Javascript to truncate the text before the end of the div and add "..."? How can I accomplish this regardless of the font size bein ...

When using Node.js and geth together, running JavaScript code may lead to the creation of zombie processes, causing the

Currently, I am utilizing a JavaScript code that connects to the web3 package on Ethereum's JSON RPC API. This code is designed to iterate through each transaction in an incoming block. If the transaction involves an internal wallet, it sends the rele ...

When using jQuery, the search for the ID within an iframe may fail if the specified condition

I have a scenario where I need to dynamically generate an iframe and its corresponding id. Now, I need to check if the generated id already exists or not. This is what my code looks like: function createIframe(intxnId){ alert("The Id is : "+"$(&apo ...

Tips for transferring data from Express to .ejs file during redirection in Node.js

When I submit the login form in my login.ejs file, the page redirects if the details are correct. If the password is wrong, however, I want to display a message in the .ejs file indicating this. Below are the details: Here is the code in my app.js file - ...