2009-08-20 10 views
3

Dies ist mein erster Ausflug in OO JS, mit Problemen.OO JS & Google Maps API: Was mache ich falsch?

Idealerweise würde ich in diesem Szenario ein mapLocation-Objekt haben, das ich einfach in Koordinaten, Icon, dem HTML-Code übergeben könnte, der beim Klicken angezeigt wird, und das wars. Ich würde es meiner Google Map auf der Seite hinzufügen und ich hätte etwas wiederverwendbares. Offensichtlich würde dies später refaktoriert werden.

Auch bin ich nicht besonders glücklich darüber, wie mein Code im Moment aussieht. :)

Hier ist das Objekt, mit dem ich komme.

function mapLocation() { 

    this.lat = 0; 
    this.lng = 0; 
    this.icon = ''; 
    this.html = ''; 
    this.getLocation = getLocation; 
} 

function getLocation() { 
    var baseIcon = new GIcon(G_DEFAULT_ICON); 
    baseIcon.shadow = "http://www.google.com/mapfiles/shadow50.png"; 
    baseIcon.iconSize = new GSize(20, 34); 
    baseIcon.shadowSize = new GSize(37, 34); 
    baseIcon.iconAnchor = new GPoint(9, 34); 
    baseIcon.infoWindowAnchor = new GPoint(9, 2); 
    var letteredIcon = new GIcon(baseIcon); 
    letteredIcon.image = this.icon; 
    var point = new GLatLng(this.lat, this.lng); 
    var marker = new GMarker(point, { icon:letteredIcon }); 

    function show() { 
     marker.openInfoWindowHtml('Lat: '+this.lat+'<br />Lng: '+this.lng+'<br /><img src="'+this.icon+'" />'); 
    } 
    alert(this.lat); 
    GEvent.addListener(marker, "click", show); 
    return marker; 
} 

Und hier ist meine Implementierung.

var a = new mapLocation; 
a.lat = 52.136369; 
a.lng = -106.696299; 
a.icon = 'http://www.google.com/mapfiles/markerA.png'; 
a.html = 'asdf fdsa'; 

var b = a.getLocation(); 
map.addOverlay(b); 

So bekomme ich Fenster angezeigt, mein Marker, aber show() -Funktion Pop-up mit undefiniert drin.

Ich bin gespannt, was ich falsch mache - wie ich falsch denke - in diesem Problem.

Danke für das Aussehen.

+0

Eine weitere Sache :) Sie sollten immer die öffnende Klammer am Ende der Zeile anstelle einer neuen Zeile in JavaScript einfügen, sonst können Sie ungerade Parsing-Probleme bekommen. Siehe http://www.youtube.com/watch?v=hQVTIJBZook&feature=player_embedded#t=30m38s – noah

+0

@Noah: Das hat wesentlich mehr mit Rückgabeanweisungen und impliziten Anweisungsbeendigungen zu tun als mit geschweiften Klammern. Ordnungsgemäß als Sicherheitsmerkmal, aber besser implicits vollständig zu vermeiden. – annakata

+0

Das ist eine großartige Präsentation, die es sich zu sehen lohnt. Der wichtige Imbiss ist, dass Code-Stil in JS mehr als nur Stil ist. – GloryFish

Antwort

0

Kann nicht ohne die zusätzlichen Funktionen drin sicher sein, aber ich stelle mir vor, es ist ein 'dieses' Referenzproblem, weil Ihre Show-Funktion keine Schließung erzeugt.

dieses (Edit: Ich bin ein Idiot 'diese' Probleme vergessen): Versuchen

function show() { 
    var x = this; 
    return function(){marker.openInfoWindowHtml('Lat: '+x.lat+'<br />Lng: '+x.lng+'<br /><img src="'+x.icon+'" />');} 
} 

GEvent.addListener(marker, "click", show()); 

Was OOJS ... Kommentare zu erklären:

//convention is to name JS classes with an uppercase character 
function MapLocation(params) 
{ 
    //instantiate from a params object to keep a flexible contructor signature 
    //(similarly you can use the native arguments object but I prefer to be explicit) 
    this.lat = (params.lat ? params.lat : 0); 
    this.lng = (params.lng ? params.lng : 0); 
    this.icon = (params.icon ? params.icon : ''); 
    this.html = (params.html ? params.html : ''); 

    //keep methods contained within the class definition 
    if (typeof(this.geolocation) == 'undefined') //execute once 
    { 
     //by binding methods with prototype you only construct a single instance of the function 
     MapLocation.prototype.getLocation = function() 
              { 
               /* ... */ 
              } 
    } 
} 

//property set at constructor 
var a = new MapLocation({lat:52.136369, lng:-106.696299, icon: 'http://www.google.com/mapfiles/markerA.png'}); 

//deferred property setting 
a.html = 'asdf fdsa'; 
+0

Ihre Formatierung ist deaktiviert ... kann den Hauptteil von getLocation nicht sehen. Die Funktion show show return wird den Wert nicht ändern. Sie müssen dies entweder in einen Verweis auf das Objekt ändern oder show als Methode des Objekts aufrufen. – noah

+0

Sie werden bemerken, dass ich das zweite Problem korrigiert habe, aber der Körper von getLocation wurde absichtlich verkürzt, daher das/* ... * /. – annakata

+0

Dies ist immer noch das Fensterobjekt. Sie müssen einen Verweis darauf in der Konstruktorfunktion speichern. – noah

0
var _this = this; 
    function show() { 
      marker.openInfoWindowHtml('Lat: '+_this.lat+'<br />Lng: '+_this.lng+'<br /><img src="'+_this.icon+'" />'); 
    } 

Denken Sie daran, dass, wenn eine Funktion als Mitglied eines Objekts aufgerufen wird, dieses === Fenster.

Auch eine saubere Art und Weise all dies auszudrücken ist:

function mapLocation() { 
    // constructor stuff 
} 

mapLocation.prototype = { 
    getLocation: function() { 
    // code for getLocation 
    } 
}; 

Dann müssen Sie nicht this.getLocation im Konstruktor zuweisen.

+0

Der fwiw-Prototyp ist besser als die Zuweisung einer nackten Methode, da er nur eine Instanz des Methodenobjekts und eine (möglicherweise unterschiedliche) Instanz pro Instanz des Klassenobjekts erstellt. – annakata