1

I need some help understanding scope in Javascript. I posted a similar question earlier and prematurely marked it as accepted. (The solution didn't work in my case).

I've got javascript (a) and jQuery script (b). I need to access some values from (a) in (b).

In (a) I've got:

function map_maker_js( args ) {
 var map = new google.maps.Map(document.getElementById( args['id'] ), myOptions);
//rest of the code for building the map goes here

google.maps.event.addListener(map, 'tilesloaded', viewport_bounds);

function viewport_bounds() {
    var bounds = map.getBounds();
    var ne = bounds.getNorthEast();
    var sw = bounds.getSouthWest();

    var maxLat = ne.lat();
    var maxLong = ne.lng();
    var minLat = sw.lat();
    var minLong = sw.lng();

    var the_maps_bounds = [maxLat, maxLong, minLat, minLong];

    //return(the_maps_bounds);

 }

}

In jQuery script (b), I need the_maps_bounds, which is calculated by viewport_bounds(). I can't simply move google.maps.event.addListener(map, 'tilesloaded', viewport_bounds); into (b), because 'map' is out of scope. This won't work in (b):

google.maps.event.addListener(map, 'tilesloaded',  function() {
    // This code will only execute after event `tilesloaded` happens

    var the_maps_bounds = viewport_bounds()

    // now do something with the bounds
    // ...
});

If I move the viewport_bounds() function outside of map_maker_js, then I'll have to add map as an argument, which won't work in (b), either.

The code that I'm working on is in a WordPress plugin. I don't think that that will affect the answer, though.

I'm learning still learning javascript. What's the best way to solve this?

Thank you


Update:

Thank you Rob W for your suggestion. This is what I've got now:

var the_maps_bounds;

function map_maker_js( args ) {
     var map = new google.maps.Map(document.getElementById( args['id'] ), myOptions);
    //rest of the code for building the map goes here

    google.maps.event.addListener(map, 'tilesloaded', viewport_bounds);

    function viewport_bounds() {
        var bounds = map.getBounds();
        var ne = bounds.getNorthEast();
        var sw = bounds.getSouthWest();

        var maxLat = ne.lat();
        var maxLong = ne.lng();
        var minLat = sw.lat();
        var minLong = sw.lng();

        the_maps_bounds = [maxLat, maxLong, minLat, minLong];

        alert(the_maps_bounds); //is the the_map_bounds working

        return(the_maps_bounds);

     }

    }

In script (b), I've got:

jQuery.noConflict();

jQuery(document).ready(function($) { //how jQuery scripts are written in WordPress

 alert(window.the_maps_bounds);

//rest of my functions

});

When I view the page, I get "undefined" in the alert box and then, an alert box with the lat longs. I also tried the alert without 'window'. And on the ready event:

$('#map').ready(function() {
     alert(the_maps_bounds);
 });

I guess that the_maps_bounds in script (b) doesn't have a value for soem reason. Is the alert firing before its value is set in script (a)? Is something else going on? Any ideas? Thank you.

3
  • It's unclear what you are asking. Could you try to rephrase this so it is in the form of a question? Commented Sep 28, 2011 at 20:34
  • Read this, and you will learn all you need about js scoping: adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting Commented Sep 28, 2011 at 21:03
  • @namuol Thank you for your message. How can I access the value of the_maps_bounds, which is set in script (a), in script (b)? Commented Sep 28, 2011 at 21:37

1 Answer 1

1

Remove var before your the_maps_bound declarations, and use this code:

var the_maps_bound;
function map_maker_js( args ) {
 var map = new google.maps.Map(document.getElementById( args['id'] ), myOptions);
//rest of the code for building the map goes
....

This way, you define the_maps_bound outside the scope of these functions. If your functions are defined in the global scope (window), the the_maps_bound variable will also be accessible through window.the_maps_bound. Note: the var declaration has to be in the closest shared parent scope in order to get the code work (see below for a more detailled explanation).

It's a good practice to use var, to prevent leaking to the global scope. When you've already defined a variable in a parent scope, omitting var inside the local scope will not leak to the global scope. Instead, the closest variable (ie the closest scope where the variable is defined) will be used. If there's not such a variable, the global scope will be used to store the variable.

Sign up to request clarification or add additional context in comments.

7 Comments

Hi @Rob W, Thank you for your comment. I edited my question and made the changes you suggested. Unfortunately, when I call alert(window.the_maps_bounds);, I get 'undefined' in script b. Any suggestions? Thanks.
Move the var the_maps_bound declaration to the global scope, eg by defining it outside any function blocks. Global leaking is an acceptable solution for this case.
Thanks for the message. I thought that I defined var the_maps_bound in the global space? It's outside any script block. I also did a test. I put var meat = 'salami'; in script (a). In script (b), I called alert(meat); outside of any script block, and I get 'salami'. So the global space is working. For some reason, the_maps_bounds isn't getting set or isn't getting returned out of the function. Or the alert on the_map_bounds in script (b) is getting called before script (a) has set the value. Not sure what I'm doing wrong.
$(document).ready immediately executes code when the HTML document is loaded. It's possible that your Google API hasn't finished loading yet when you're showing an alert dialog. To verify whether the variable has been defined or not, add var the_maps_bound=null in the global scope. When you see null in the alert box, the cause is likely to be at the sequence of execution.
Thank you Rob. We're making progress. I'm getting 'null'. So, the now I have to figure out how to call the alert after map_maker_js has run.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.