Mark Lewis
Mark Lewis

Reputation: 179

Javascript Object Literal Scope Issue?

I'm having a hard time understanding why this.$map and this.markers are undefined. Here's the code I'm working with and I have added comments where I expect these variables to supply a value:

(function($) {
    'use strict';

    var A = {

        /**
         * Initialize the A object
         */
        init: function() {
            this.$map = this.renderMap();
            this.markers = this.getMarkers();

            this.renderMarkers();
        },

        renderMap: function() {

            var url = 'http://a.tiles.mapbox.com/v3/delewis.map-i3eukewg.jsonp';

            // Get metadata about the map from MapBox
            wax.tilejson(url, function(tilejson) {
                var map = new L.Map('map', {zoomControl: false});

                var ma = new L.LatLng(42.2625, -71.8028);

                map.setView(ma, 8);

                // Add MapBox Streets as a base layer
                map.addLayer(new wax.leaf.connector(tilejson));

                return function() {
                    return map;
                };
            });
        },

        renderMarkers: function() {
            var geojsonLayer = new L.GeoJSON(null, {
                pointToLayer: function (latlng){
                    return new L.CircleMarker(latlng, {
                        radius: 8,
                        fillColor: "#ff7800",
                        color: "#000",
                        weight: 1,
                        opacity: 1,
                        fillOpacity: 0.8
                    });
                }
            });

            geojsonLayer.addGeoJSON(this.markers); // this.markers is undefined
            this.$map.addLayer(geojsonLayer); // this.$map is undefined

        },

        getMarkers: function() {
            $.getJSON("/geojson/", function (data) {
                return data;
            });
        }
    };

    /**
     * A interactions
     */
    $(document).ready(function() {
        A.init()
    });

})(jQuery.noConflict());

I have spent much of the day searching and I think I'm missing something fundamental here, but I don't get it.

Upvotes: 0

Views: 308

Answers (2)

tobyodavies
tobyodavies

Reputation: 28099

Neither the renderMap, nor getMarkers methods return any value, consequently their return value is undefined.

It looks like you are trying to initialize these fields from an ajax request, which is not necessarily a good idea.

What you probably ought to do is something like:

getMarkers: function(callback){
    var result = this;
    $.getJSON("url", function(jsonData){ 
        result.markers = jsonData; 
        if(callback) callback()
     });
},

which will lazily initialize the fields of the object as they become available.

NB: AJAX is asynchronous you cannot rely on this callback setting the member quickly, or indeed ever (it could fail). This suggests you need to think a bit more about your design, and try to use callbacks more.

e.g. modify the getMarkers and renderMap functions as above to take a callback that is called after the data is stored then change init to:

init: function(){
    var res = this;
    var post_init_callback = function(){
        if(res.$map != undefined && res.markers!=undefined){
            //this will only run after both ajax calls are complete
            res.renderMarkers();  
        }
    };
    this.getMarkers(post_init_callback);
    this.renderMap(post_init_callback);
},

Upvotes: 3

Alxandr
Alxandr

Reputation: 12423

The problem here is that you call return inside another function. What you're essentially doing is defining getMarkers (the simplest example) as this:

getMarkers: function() {
    $.getJSON('/geojson/', some_random_func);
}

At which point it becomes obious that getMarkers doesn't actually return anything (ergo undefined). The same goes for your renderMap function. Also in this case your "some_random_func" is defined as function(data) { return data; } but what does it return it to? Truth is that the some_random_func is called by jQuery itself, and AFAIK jQuery doesn't care at all for the return-value of it's success-function.

Upvotes: 1

Related Questions