views:

162

answers:

3

I have the function below. Everything works fine except for the Push, Pop and Remove method. These method should be called by the event-handler. This event is fired by the google maps api.

The problem is that when the event is fired, these method are not found. I have a "Push is not defined" error message.

I tried with this but that's not working.

How do I call the public method from the event handler?

Thanks guys

function Track(mapContainer) {
var map = mapContainer;
var points = new Array();

var isEditMode = false;

var clickListener;

this.Push = function(point) { ... }

this.Pop = function() { ... }

this.Remove = function(point) { ... }

//Enable / disable the marker placements
this.PlaceWaypoint = function(isPlacing) {
    if (isPlacing != true) {
        if (clickListener != null) {
            google.maps.event.removeListener(clickListener);
            clickListener = null;
        }
    } else {
        clickListener = map.AddEvent("click", function(event) {
            if (!IsDoubleClick()) {
                var point = map.PlaceMarker(new WayPoint(event.latLng))
                point.RemoveListener(function() { Remove(point); });
                Push(point);
            } else {
                Pop();
            }
        });
    }
}
}
+1  A: 

First of all Pop and Push is not global, second this in the inner scope has another meaning. So you can use closure and rename the "this" to variable of more global scope.

function Track(mapContainer) {

//....
var $this = this;

//Enable / disable the marker placements
this.PlaceWaypoint = function(isPlacing) {
    if (isPlacing != true) {
        if (clickListener != null) {
            google.maps.event.removeListener(clickListener);
            clickListener = null;
        }
    } else {
        clickListener = map.AddEvent("click", function(event) {
            if (!IsDoubleClick()) {
                var point = map.PlaceMarker(new WayPoint(event.latLng))
                point.RemoveListener(function() { $this.Remove(point); });
                $this.Push(point);
            } else {
                $this.Pop();
            }
        });
    }
}
}
Artem Barger
it's probably better to scope this to the function by adding var in front of it, otherwise if we have multiple instances of Track, the $this-variable will be overwritten and methods invoked on the wrong instance.
PatrikAkerstrand
@Machine, thank got pointing to mistake, have fixed it accordingly.
Artem Barger
+1  A: 

You've got a closure/binding problem. One convention that is frequently used it to assign a variable called self of that, which can later be used in place of this, thanks to the closure properties of JS.

function Track(mapContainer) {
   var map = mapContainer,
       points = new Array(),
       isEditMode = false,
       clickListener,
       // Make a variable self that points to this, that can be used inside closures
       // where the original context is lost
       self = this;

   this.Push = function(point) { ... }

   this.Pop = function() { ... }

   this.Remove = function(point) { ... }

   //Enable / disable the marker placements
   this.PlaceWaypoint = 
       function(isPlacing) {
            if (isPlacing != true) {
                if (clickListener != null) {
                    google.maps.event.removeListener(clickListener);
                    clickListener = null;
                }
            } else {
                clickListener = map.AddEvent("click", function(event) {
                    if (!IsDoubleClick()) {
                        var point = map.PlaceMarker(new WayPoint(event.latLng))
                        point.RemoveListener(function() { Remove(point); });
                        // Use the closure reference self instead of this
                        self.Push(point);
                    } else {
                        // Use the closure reference self instead of this
                        self.Pop();
                    }
                });
        };
}
PatrikAkerstrand
+1  A: 

this always refers to the context of the current function, so if you use this in your event handler it refers to that function calls this, not the this in your Track function.

To create a closure that accesses the this of an outer scope, you need to assign that this to a new variable which can be accessed from the inner function:

var self = this;
this.PlaceWaypoint = function(isPlacing) {
   // ...
   self.Pop();
   // ...
}
sth