-1

I'm building this app with knockout js and google maps javascript api. What I'm trying to do is populate some markers for a set of pre defined locations. i want to be able to track which marker has been click or selected so that a panel can slide in from the bottom of the screen to show pictures and business info of that location. I know i can just use the infowindow to display the info but i don't want to do that.

var Point = function(place) {
    var self = this;
    self.name = place.name;
    self.pos = place.pos;
    self.type = place.type;
    self.description = place.description;
    self.clicked = map.getZoom();
    /**
        Create a marker for this destination.
  */
    self.marker = new google.maps.Marker({
        map: map,
        position: place.pos,
        title: place.name,
        icon: image,
        optimized: false,
        animation: google.maps.Animation.DROP
    });

    self.isVisible = ko.observable(false);
    /**
        Toggle for the visibility of each marker on map.
  */
  self.isVisible.subscribe(function(currentState) {
    if (currentState) {
      self.marker.setMap(map);
    } else {
      self.marker.setMap(null);
    }
  });

  self.isVisible(true);

  /**
        To re position the target marker and the map view to compensate for the shifted map view panel when the search menu pushes in from the left when the location is being clicked on the menu.
  */
    self.focusSearch = function() {
        map.setZoom(16);
        map.setCenter(self.marker.position);
        map.panBy(200,0);
        self.open();
    }
    /**
        To re position the target marker and the map view to compensate for the shifted map view panel when the menu slides in from the left when the location is being clicked on the menu.
  */
    self.focus = function() {
        map.setZoom(16);
        map.setCenter(self.marker.position);
        map.panBy(-200, 0);
        self.open();
    }
    /**
        Display the name and a brief description of the location in a infowindow for the corresponding marker. Also checks if the map view, in this case the zoom level has changed, if so then change the map view and re center it to the marker of the loaction that is selected. Applies to only when the regular menu is active.
    */
    self.open = function() {
        var contentString = "<h2>" + place.name + "</h2><br>";
        infowindow.setContent(contentString + place.description);
        infowindow.open(map, self.marker);
    }
    /**
        Dismiss the infowindow.
    */
    self.close = function() {
        infowindow.close();
        self.marker.setAnimation(null);
    }
    /**
        Additional event listeners for the marker.
    */
    self.marker.addListener("mouseover", function() {
        self.open();
        self.marker.setAnimation(google.maps.Animation.BOUNCE);
    });

    self.marker.addListener("mouseout", function() {
        self.marker.setAnimation(null);
    });

    self.marker.addListener("click", function() {
        map.setZoom(16);
        map.setCenter(self.marker.position);
        pushLeft.close();
        slideLeft.close();
        slideBottom.open();
        currentPoint = self;
        self.open();
    });
}
/**
        This is our ViewModel that handles displaying a menu of destinations, filter/search through the menu and finally displaying markers of these destinations on the map.
*/
var ViewModel = function(list) {
    var self = this;
    /**
     * Create a Place object for each object in the initial array and
     * place them in a new observable array.
    */
    self.allPlaces = ko.observableArray(list.map(function(place) {
        return new Point(place);
    }));

    self.search = ko.observable("");
    currentPoint = ko.observable();

    /**
     * Filter locations out of the menu view for any unmatched results.
     * Filter by name, description and type.
    */
    self.searchResult = ko.pureComputed(function() {
        var q = self.search().toLowerCase();
        return self.allPlaces().filter(function(place) {
            return ((place.name.toLowerCase().indexOf(q) >= 0) || (place.description.toLowerCase().indexOf(q) >= 0) || (place.type.toLowerCase().indexOf(q) >= 0));
        });
    });
    /**
     * Filter markers out of the map view for any unmatched results.
     * Filter by name, description and type.
    */
    self.filterMarkers = ko.computed(function () {
    var q  = self.search().toLowerCase();
    return ko.utils.arrayFilter(self.allPlaces(), function (place) {
        var doesMatch = ((place.name.toLowerCase().indexOf(q) >= 0) || (place.description.toLowerCase().indexOf(q) >= 0) || (place.type.toLowerCase().indexOf(q) >= 0));
        place.isVisible(doesMatch);
        return doesMatch;
    });
});
}
Steven Kwok
  • 199
  • 4
  • 15
  • You can do this by asigning ids to the markers- See this http://stackoverflow.com/questions/2564320/adding-ids-to-google-map-markers – Ankit Oct 01 '16 at 22:29
  • How does adding an id to the marker object help? I need to use observable to handle the view changes such. – Steven Kwok Oct 02 '16 at 02:36

1 Answers1

0

Turns out i only needed 3 extra lines of code to make it work. declare var viewModel in the outermost scope so that the Point object can have access to it. Then inside viewModel do self.selected = ko.observable(self.allPlaces()[0]); to set the initial selected object which is essential because if I leave the observable empty, the view model will throw an error as i'm binding selected to the html. lastly, in the marker click even listener, add viewModel.selected = self so that the selected observable will be updated everytime a marker is clicked.

Steven Kwok
  • 199
  • 4
  • 15