hi guys, this project is about creating a google map using knockout.js.
var map;
// Create a new blank array for all the listing markers.
var markers = [];
// Create placemarkers array to use in multiple functions to have control
// over the number of places that show.
var placeMarkers = [];
// These are the real estate listings that will be shown to the user.
// Normally we'd have these in a database instead.
var locations = [{
title: "Ble Cafe-Restaurant </br> Street: Agias Sofias 19, 54623",
location: {
lat: 40.632286,
lng: 22.944743
}
},
{
title: 'Olympion Bar-Restaurant </br> Street: Aristotelous Square 10, 54623',
location: {
lat: 40.632744,
lng: 22.941767
}
},
{
title: 'Olive and Oregon Restaurant </br> Street: Ermou 28, 54624',
location: {
lat: 40.634679,
lng: 22.943193
}
},
{
title: 'Mojo Cafe </br> Street: Aristotelous 4, 54623',
location: {
lat: 40.631824,
lng: 22.940958
}
},
{
title: 'Seven Seas Restaurant </br> Street: Kalapothaki 10, 54624',
location: {
lat: 40.633300,
lng: 22.939356
}
},
{
title: 'Varelakia Gyros </br> Street: Riga Fereou 97, 56728',
location: {
lat: 40.574634,
lng: 22.949332
}
}
];
function initMap() {
// Create a styles array to use with the map.
var styles = [
{
featureType: 'water',
stylers: [
{ color: '#31A9B8' }
]
},{
featureType: 'administrative',
elementType: 'labels.text.stroke',
stylers: [
{ color: '#ffffff' },
{ weight: 6 }
]
},{
featureType: 'administrative',
elementType: 'labels.text.fill',
stylers: [
{ color: '#e85113' }
]
},{
featureType: 'road.highway',
elementType: 'geometry.stroke',
stylers: [
{ color: '#efe9e4' },
{ lightness: -40 }
]
},{
featureType: 'transit.station',
stylers: [
{ weight: 9 },
{ hue: '#e85113' }
]
},{
featureType: 'road.highway',
elementType: 'labels.icon',
stylers: [
{ visibility: 'off' }
]
},{
featureType: 'water',
elementType: 'labels.text.stroke',
stylers: [
{ lightness: 100 }
]
},{
featureType: 'water',
elementType: 'labels.text.fill',
stylers: [
{ lightness: -100 }
]
},{
featureType: 'poi',
elementType: 'geometry',
stylers: [
{ visibility: 'on' },
{ color: '#f0e4d3' }
]
},{
featureType: 'road.highway',
elementType: 'geometry.fill',
stylers: [
{ color: '#efe9e4' },
{ lightness: -25 }
]
}
];
function Coord(title, lat, ing) {
var self = this;
self.lat = ko.observable(lat);
self.ing = ko.observable(ing);
}
function Place(title, address, lat, ing) {
var self = this;
self.title = title;
self.address = address;
self.coords = ko.observable(new Coord(lat,ing));
//create a function to make the list of locations clikable
self.myList = function() {
if(title){
map.setZoom(18);
map.panTo(position);
map.setCenter(markers[title]);
}
};
}
function LocationsViewModel() {
var self = this;
self.query = ko.observable('');
self.places = ko.observableArray([
new Place("Ble Cafe-Restaurant", 40.632286, 22.944743, "Street: Agias Sofias 19, 54623"),
new Place("Olympion Bar-Restaurant", 40.632744, 22.941767, "Street: Aristotelous Square 10, 54623"),
new Place("Olive and Oregon Restaurant", 40.634679, 22.943193, "Street: Aristotelous Square 10, 54623"),
new Place("Mojo Cafe", 40.631824, 22.940958, "Aristotelous 4, 54623"),
new Place("Seven Seas Restaurant", 40.633300, 22.939356, "Kalapothaki 10, 54624"),
new Place("Varelakia Gyros", 40.574634, 22.949332, "Street: Riga Fereou 97, 56728"),
]);
self.search = function(value) {
viewModel.places.removeAll();
for(var x in places) {
if(places[x].title.toLowerCase().indexOf(value.toLowerCase()) >= 0) {
viewModel.places.push(places[x]);
}
}
};
}
ko.applyBindings(new LocationsViewModel());
// Constructor creates a new map - only center and zoom are required.
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 40.640063, lng: 22.944419},
zoom: 13,
styles: styles,
mapTypeControl: false
});
var largeInfowindow = new google.maps.InfoWindow();
// Style the markers a bit. This will be our listing marker icon.
var defaultIcon = makeMarkerIcon('FE0000');
// Create a "highlighted location" marker color for when the user
// mouses over the marker.
var highlightedIcon = makeMarkerIcon('FDF6F6');
// The following group uses the location array to create an array of markers on initialize.
for (var i = 0; i < locations.length; i++) {
// Get the position from the location array.
var position = locations[i].location;
var title = locations[i].title;
// Create a marker per location, and put into markers array.
var marker = new google.maps.Marker({
//with map:map markers appears immediately after map has been load
map:map,
position: position,
title: title,
animation: google.maps.Animation.DROP,
icon: defaultIcon,
id: i
});
// Push the marker to our array of markers.
markers.push(marker);
// Create an onclick event to open the large infowindow at each marker.
marker.addListener('click', function() {
populateInfoWindow(this, largeInfowindow);
});
// Two event listeners - one for mouseover, one for mouseout,
// to change the colors back and forth.
marker.addListener('mouseover', function() {
this.setIcon(highlightedIcon);
});
marker.addListener('mouseout', function() {
this.setIcon(defaultIcon);
});
}
}//end if init
// This function populates the infowindow when the marker is clicked. We'll only allow
// one infowindow which will open at the marker that is clicked, and populate based
// on that markers position.
function populateInfoWindow(marker, infowindow) {
// Check to make sure the infowindow is not already opened on this marker.
if (infowindow.marker != marker) {
// Clear the infowindow content to give the streetview time to load.
infowindow.setContent('');
infowindow.marker = marker;
// Make sure the marker property is cleared if the infowindow is closed.
infowindow.addListener('closeclick', function() {
infowindow.marker = null;
});
var streetViewService = new google.maps.StreetViewService();
var radius = 50;
// In case the status is OK, which means the pano was found, compute the
// position of the streetview image, then calculate the heading, then get a
// panorama from that and set the options
function getStreetView(data, status) {
if (status == google.maps.StreetViewStatus.OK) {
var nearStreetViewLocation = data.location.latLng;
var heading = google.maps.geometry.spherical.computeHeading(
nearStreetViewLocation, marker.position);
infowindow.setContent('<div>' + marker.title + '</div><div id="pano"></div>');
var panoramaOptions = {
position: nearStreetViewLocation,
pov: {
heading: heading,
pitch: 50
}
};
var panorama = new google.maps.StreetViewPanorama(
document.getElementById('pano'), panoramaOptions);
} else {
infowindow.setContent('<div>' + marker.title + '</div>' +
'<div>No Street View Found</div>');
}
}
// Use streetview service to get the closest streetview image within
// 50 meters of the markers position
streetViewService.getPanoramaByLocation(marker.position, radius, getStreetView);
// Open the infowindow on the correct marker.
infowindow.open(map, marker);
}
}
// This function takes in a COLOR, and then creates a new marker
// icon of that color. The icon will be 21 px wide by 34 high, have an origin
// of 0, 0 and be anchored at 10, 34).
function makeMarkerIcon(markerColor) {
var markerImage = new google.maps.MarkerImage(
'|40|_|%E2%80%A2',
new google.maps.Size(21, 34),
new google.maps.Point(0, 0),
new google.maps.Point(10, 34),
new google.maps.Size(21,34));
return markerImage;
}
// This function creates markers for each place found in either places search.
function createMarkersForPlaces(places) {
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < places.length; i++) {
var place = places[i];
var icon = {
url: place.icon,
size: new google.maps.Size(35, 35),
origin: new google.maps.Point(0, 0),
anchor: new google.maps.Point(15, 34),
scaledSize: new google.maps.Size(25, 25)
};
// Create a marker for each place.
var marker = new google.maps.Marker({
map: map,
icon: icon,
position: place.geometry.location,
id: place.place_id
});
// Create a single infowindow to be used with the place details information
// so that only one is open at once.
var placeInfoWindow = new google.maps.InfoWindow();
// If a marker is clicked, do a place details search on it in the next function.
marker.addListener('click', function() {
if (placeInfoWindow.marker == this) {
console.log("This infowindow already is on this marker!");
} else {
getPlacesDetails(this, placeInfoWindow);
}
});
placeMarkers.push(marker);
if (place.geometry.viewport) {
// Only geocodes have viewport.
bounds.union(place.geometry.viewport);
} else {
bounds.extend(place.geometry.location);
}
}
map.fitBounds(bounds);
}
// This is the PLACE DETAILS search - it's the most detailed so it's only
// executed when a marker is selected, indicating the user wants more
// details about that place.
function getPlacesDetails(marker, infowindow) {
var service = new google.maps.places.PlacesService(map);
service.getDetails({
}, function(place, status) {
if (status === google.maps.places.PlacesServiceStatus.OK) {
// Set the marker property on this infowindow so it isn't created again.
infowindow.marker = marker;
var innerHTML = '<div>';
innerHTML += '<strong>' +
place.name + '</strong>';
}
if (place.formatted_address) {
innerHTML += '<br>' + place.formatted_address;
}
if (place.formatted_phone_number) {
innerHTML += '<br>' + place.formatted_phone_number;
}
if (place.opening_hours) {
innerHTML += '<br><br><strong>Hours:</strong><br>' +
place.opening_hours.weekday_text[0] + '<br>' +
place.opening_hours.weekday_text[1] + '<br>' +
place.opening_hours.weekday_text[2] + '<br>' +
place.opening_hours.weekday_text[3] + '<br>' +
place.opening_hours.weekday_text[4] + '<br>' +
place.opening_hours.weekday_text[5] + '<br>' +
place.opening_hours.weekday_text[6];
}
if (place.photos) {
innerHTML += '<br><br><img src="' + place.photos[0].getUrl(
{maxHeight: 100, maxWidth: 200}) + '">';
}
innerHTML += '</div>';
infowindow.setContent(innerHTML);
infowindow.open(map, marker);
// Make sure the marker property is cleared if the infowindow is closed.
infowindow.addListener('closeclick', function() {
infowindow.marker = null;
});
}
});
}