I'm unable to fire event on pano_change in the Streetview that is embedded in infowindow. I need to get the array getLinks() and getPosition() of the object StreetViewPanorama each time the user navigates in Streetview infowindow. It is declared as below. I really don't understand why (it works for events on marker and infowindow).
//code here
var contentString = '<input type="button" value="Grab this picture" onClick="captureImage()" /> <div id="content" style="width:200px;height:200px;"></div>';
//code here
var infowindow = new google.maps.InfoWindow({
content: contentString
});
//code here//
google.maps.event.addListener(infowindow, 'domready', function() {
if (pano != null) {
pano.unbind("position");
pano.setVisible(false);
}
pano = new google.maps.StreetViewPanorama(document.getElementById("content"), {
navigationControl: true,
navigationControlOptions: {style: google.maps.NavigationControlStyle.ANDROID},
enableCloseButton: false,
addressControl: false,
linksControl: false
});
pano.bindTo("position", marker);
pano.setVisible(true);
});
You need to add google.maps.event.addListener(pano, 'links_changed', XXXX) and google.maps.event.addListener(pano, 'position_changed', XXXXX) in order to get the events.
Initialization
var pano = new google.maps.StreetViewPanorama(<element>, panoramaOptions);
google.maps.event.addListener(pano, 'pano_changed', function() {
// whatever
});
google.maps.event.addListener(pano, 'links_changed', function() {
var links = pano.getLinks();
for (var i in links) {
// whatever
}
});
google.maps.event.addListener(panorama, 'position_changed', function() {
var newPos = pano.getPosition();
});
google.maps.event.addListener(pano, 'pov_changed', function() {
var newPoV = panorama.getPov();
});
Now, every time you have a change in any of those three events (links, pov, position) the relevant function gets called.
Related
im using Googlemap JS API, i have some markers fetched from my Database and an infowindow foreach marker, on each infowindow i have a button wish pushes to another page with a certain variable, i tried to use ngZone, im not really familiar with it but i tried x), here's my code:
// GET request to get data from database
for(var i=0;i<data.length;i++)
{
var ouvrier=data[i].firstname+' '+data[i].lastname; //Getting data from db
var Latlng = new google.maps.LatLng(data[i].lat,data[i].lon);
var marker = new google.maps.Marker({
position: Latlng,
map: this.map,
labelAnchor: new google.maps.Point(22, 0),
draggable:false,
icon: { url : 'assets/imgs/worker.png',scaledSize: new google.maps.Size(70, 70)
},
});
var infowindow = new google.maps.InfoWindow({
content: "Name: "+ouvrier+" <input type='button' id='clickableItem' value='consulter profile' >"
});
google.maps.event.addListener(infowindow, 'domready', () => {
var clickableItem = document.getElementById('clickableItem');
clickableItem.addEventListener('click', () => {
this.zone.run( () => { //Im using ngZone
console.log("wlidoz "+ data[i].idprof);
this.navCtrl.push(ProfilPage, {
profilId: data[i].idprof // PROBLEM HERE
});
});
});
});
marker.addListener('click', event => {
infowindow.open(this.map, marker);
});
}
Everything is working fine, the map is loading..etc
But when i click on that button, nothing happens, i tried to console.log that data[i].idprof inside the ngZone but its undefined, but before the listener the console.log is working
I fixed it, i just declared a variable berfore the google.maps.event.addLister :
let idz=data[i].idprof;
let that=this;
google.maps.event.addListener(infowindow, 'domready', () => {
var clickableItem = document.getElementById('clickableItem');
clickableItem.addEventListener('click', () => {
that.zone.run( () => {
that.navCtrl.push(ProfilPage, {
profilId: idz
});
});
});
});
If anyone has a better solution, i'll take it
Im trying to code a functionality so when I click on a certain location button that markers info window pops up. Ive got the code to console log the certain title and location of the marker, but when i try to call the infowindow in the viewmodel it comes up undefined. I know that the Infowindow is in the init function for google map, i cant seem to figure out how to open it from the viewmodel
and here is my code for the view model:
function viewModel() {
this.marker = locationArray().location;
this.openWindow = function(location){
if(this.marker){
console.log(this.marker);
};
}
}
and my click event:
google.maps.event.addListener(marker,'click', (function(marker){
return function() {
viewModel()
infoWindow.setContent("<div>" + marker.title + "</div>");
infoWindow.open( map, marker);
}
})(marker));
here is my google map api, hopefully this will help :
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 41.764117, lng: -72.676470},
zoom: 13,
styles: style
});
// Iterates through the locationArray and gives the marker a proper
// location.
for(var i = 0; i < locationArray().length; i++){
var locations = locationArray()[i].location;
var title = locationArray()[i].title;
var marker = new google.maps.Marker({
position: locations,
map: map,
title: title,
animation: google.maps.Animation.DROP
});
locationArray()[i].marker = marker;
var message = "hello world!";
var infoWindow = new google.maps.InfoWindow({
content: title,
position: locations
});
google.maps.event.addListener(marker,'click', (function(marker){
return function() {
viewModel();
infoWindow.setContent("<div>" + marker.title + "</div>");
infoWindow.open( map, marker);
}
})(marker));
};
};
ko.applyBindings(new viewModel());
You definition of marker in the ViewModel is ambiguous. You should in general define the observables inside the ViewModel.
function ViewModel(data) {
var self = this;
self.locations = ko.observableArray(data.locations || []);
self.showMarker(function(loc) { // bind this to click (in html)
loc.marker.showInfo(); // I'm not sure if loc.marker.click() would work
});
}
var locations = []; // your list of locations
ko.applyBindings( new ViewModel({locations: locations}) );
And you can bind the click event of your marker in a simpler way, that'll also help to easily call the
marker.showInfo = function() {
infoWindow.setContent("<div>" + this.title + "</div>");
infoWindow.open( map, this);
};
google.maps.event.addListener(marker,'click', marker.showInfo);
I recently started programing in javascript.
I have added a layer control window to my map. It's open by default (This works.). Now I want to add a close button to the layer control window. Is that possible?
This my code:
$ (document).ready(function init(){
// initiate leaflet map
var map = new L.Map('cartodb-map', {
center: [51,9],
zoom: 4,
minZoom:3,
maxZoom: 16,
});
//load basemap
var OSM= new L.tileLayer('http://a{s}.acetate.geoiq.com/tiles/acetate-hillshading/{z}/{x}/{y}.png',
{attribution: '© OpenStreetMap'}).addTo(map);
//load data from CartoDB
var layerUrl= 'http://intermodalmap.cartodb.com/api/v2/viz/0931f4e4-76f8-11e4-0e9d821ea90d/viz.json';
//load satellit map
var Esri_WorldImagery = new L.tileLayer('http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
attribution: 'Tiles © Esri — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community' });
var baseLayers = { "Standardkarte": OSM,
"Satellitenkarte": Esri_WorldImagery };
//create map
cartodb.createLayer(map, layerUrl,
{https: true,
legends: true,
cartodb_logo:false,
layerIndex: 1
})
.addTo(map)
.on('done', function() {
});
L.Control.Custom = L.Control.Layers.extend({
onAdd: function () {
this._initLayout();
this._addButton();
this._update();
return this._container;
},
_addButton: function () {
var elements = this._container.getElementsByClassName('leaflet-control-layers-list');
var button = L.DomUtil.create('button', 'my-button-class', elements[0]);
button.innerText = 'Close control';
L.DomEvent.on(button, 'click', function(e){
L.DomEvent.stop(e);
this._collapse();
}, this);
}
});
var control = new L.Control.Custom(baseLayers, {"Alle Terminals":layerUrl}, {collapsed:false}).addTo(map);
// create a fullscreen button and add it to the map
L.control.fullscreen({
position: 'topleft', // change the position of the button can be topleft, topright, bottomright or bottomleft, defaut topleft
title: 'Open fullscreen', // change the title of the button, default Full Screen
titleCancel: 'Exit fullscreen mode', // change the title of the button when fullscreen is on, default Exit Full Screen
content: null, // change the content of the button, can be HTML, default null
forceSeparateButton: true
}).addTo(map);
// events are fired when entering or exiting fullscreen.
map.on('enterFullscreen', function(){
console.log('entered fullscreen');
});
map.on('exitFullscreen', function(){
console.log('exited fullscreen');
});
//add scale
L.control.scale({metric:"m", position:"bottomright", imperial:false}).addTo(map);
//end of function init
}
)
You can extend L.Control.Layers and add elements to it's container, attach eventhandlers, whatever you want. Something like this:
L.Control.Custom = L.Control.Layers.extend({
onAdd: function () {
this._initLayout();
this._addButton();
this._update();
return this._container;
},
_addButton: function () {
var elements = this._container.getElementsByClassName('leaflet-control-layers-list');
var button = L.DomUtil.create('button', 'my-button-class', elements[0]);
button.innerText = 'Close control';
L.DomEvent.on(button, 'click', function(e){
L.DomEvent.stop(e);
this._collapse();
}, this);
}
});
Example: http://plnkr.co/edit/Je7c0m?p=preview
cartodb.createLayer(map, layerUrl, {
layerIndex: 1
}).addTo(map)
.on('done', function(layer) {
L.control.layers(baseLayers,
{data:layer},
{collapsed:false}
).addTo(map);
document.getElementById('closeBtn').addEventListener('click', function() {
layer.setAttribute('style', 'display: none;').hide();
});
});
// and more shortly if jquery exists
$('#closeBtn').click(function() {
layer.hide();
});
Hello I'm trying to bind Google Maps with Knockout script.
Nearly everything works but I can't force infowindows to show up on event.
Without Knockout my code works but with it doesn't.
Below my js code:
var infowindow;
function point(name, lat, long) {
this.name = name;
this.lat = ko.observable(lat);
this.long = ko.observable(long);
var marker = new google.maps.Marker({
position: new google.maps.LatLng(lat, long),
title: name,
map: map,
draggable: true
});
//if you need the poition while dragging
google.maps.event.addListener(marker, 'drag', function () {
var pos = marker.getPosition();
this.lat(pos.lat());
this.long(pos.lng());
}.bind(this));
//if you just need to update it when the user is done dragging
google.maps.event.addListener(marker, 'dragend', function () {
var pos = marker.getPosition();
this.lat(pos.lat());
this.long(pos.lng());
}.bind(this));
google.maps.event.addListener(marker, 'mouseover', function () {
infowindow = new google.maps.InfoWindow({ content: "empty" });
console.log("mouseover");
infowindow.setContent(this.title);
infowindow.open(map, this);
}.bind(this));
}
var map = new google.maps.Map(document.getElementById('googleMap'), {
zoom: 5,
center: new google.maps.LatLng(55, 11),
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var viewModel = {
points: ko.observableArray([
new point('Test1', 55, 11),
new point('Test2', 56, 12),
new point('Test3', 57, 13)])
};
function addPoint() {
viewModel.points.push(new point('a', 58, 14));
}
ko.applyBindings(viewModel);
Now my question:
Is it simple way to make it works. If yes can anyone suggest me where should I look for it?
Could be your use of this.
Add var self = this; as the first line within point function & use self to refer to properties within point.
In the mouseover event, does this refer to the marker, the map, or viewmodel? If the drag event are setting values correctly, then this is the point viewmodel, in which case within the mouseover event you called this.title. There is no title...
function point(name, lat, long) {
var self = this;
self.name = name;
self.lat = ko.observable(lat);
self.long = ko.observable(long);
var marker = new google.maps.Marker({
position: new google.maps.LatLng(lat, long),
title: name,
map: map,
draggable: true
});
//if you need the poition while dragging
google.maps.event.addListener(marker, 'drag', function () {
var pos = marker.getPosition();
self.lat(pos.lat());
self.long(pos.lng());
}.bind(this));
//if you just need to update it when the user is done dragging
google.maps.event.addListener(marker, 'dragend', function () {
var pos = marker.getPosition();
self.lat(pos.lat());
self.long(pos.lng());
}.bind(this));
google.maps.event.addListener(marker, 'mouseover', function () {
infowindow = new google.maps.InfoWindow({ content: "empty" });
console.log("mouseover");
infowindow.setContent(marker.title);
infowindow.open(map, this);
}.bind(this));
}
I have never used knockout myself but integrating it with maps does not look simple, here are some reading materials: http://www.codeproject.com/Articles/351298/KnockoutJS-and-Google-Maps-binding
http://www.codeproject.com/Articles/387626/BikeInCity-2-KnockoutJS-JQuery-Google-Maps
Google maps and knockoutjs
The maps code you have provided looks correct so I assume the issue lies with the knockout integration.
On my site, I'm using Google Maps API v3 to place house markers on the map.
The InfoWindows stay open unless you explicitly click the close icon. Meaning, you can have 2+ InfoWindows open at a time if you hover over the map marker.
Question: How do I make it so that only the current active InfoWindow is open and all other InfoWindows are closed? Meaning, no more than 1 InfoWindow will be open at a time?
There is a close() function for InfoWindows. Just keep track of the last opened window, and call the close function on it when a new window is created.
alternative solution for this with using many infowindows:
save prev opened infowindow in a variable and then close it when new window opened
var prev_infowindow =false;
...
base.attachInfo = function(marker, i){
var infowindow = new google.maps.InfoWindow({
content: 'yourmarkerinfocontent'
});
google.maps.event.addListener(marker, 'click', function(){
if( prev_infowindow ) {
prev_infowindow.close();
}
prev_infowindow = infowindow;
infowindow.open(base.map, marker);
});
}
//assuming you have a map called 'map'
var infowindow = new google.maps.InfoWindow();
var latlng1 = new google.maps.LatLng(0,0);
var marker1 = new google.maps.Marker({position:latlng1, map:map});
google.maps.event.addListener(marker1, 'click',
function(){
infowindow.close();//hide the infowindow
infowindow.setContent('Marker #1');//update the content for this marker
infowindow.open(map, marker1);//"move" the info window to the clicked marker and open it
}
);
var latlng2 = new google.maps.LatLng(10,10);
var marker2 = new google.maps.Marker({position:latlng2, map:map});
google.maps.event.addListener(marker2, 'click',
function(){
infowindow.close();//hide the infowindow
infowindow.setContent('Marker #2');//update the content for this marker
infowindow.open(map, marker2);//"move" the info window to the clicked marker and open it
}
);
This will "move" the info window around to each clicked marker, in effect closing itself, then reopening (and panning to fit the viewport) in its new location. It changes its contents before opening to give the desired effect. Works for n markers.
My solution.
var map;
var infowindow = new google.maps.InfoWindow();
...
function createMarker(...) {
var marker = new google.maps.Marker({
...,
descrip: infowindowHtmlContent
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.setOptions({
content: this.descrip,
maxWidth:300
});
infowindow.open(map, marker);
});
Declare a variable for active window
var activeInfoWindow;
and bind this code in marker listener
marker.addListener('click', function () {
if (activeInfoWindow) { activeInfoWindow.close();}
infowindow.open(map, marker);
activeInfoWindow = infowindow;
});
From this link http://www.svennerberg.com/2009/09/google-maps-api-3-infowindows/:
Teo: The easiest way to do this is to
just have one instance of the
InfoWindow object that you reuse over
and over again. That way when you
click a new marker the infoWindow is
“moved” from where it’s currently at,
to point at the new marker.
Use its setContent method to load it
with the correct content.
There is a easier way besides using the close() function. if you create a variable with the InfoWindow property it closes automatically when you open another.
var info_window;
var map;
var chicago = new google.maps.LatLng(33.84659, -84.35686);
function initialize() {
var mapOptions = {
center: chicago,
zoom: 14,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
info_window = new google.maps.InfoWindow({
content: 'loading'
)};
createLocationOnMap('Location Name 1', new google.maps.LatLng(33.84659, -84.35686), '<p><strong>Location Name 1</strong><br/>Address 1</p>');
createLocationOnMap('Location Name 2', new google.maps.LatLng(33.84625, -84.36212), '<p><strong>Location Name 1</strong><br/>Address 2</p>');
}
function createLocationOnMap(titulo, posicao, conteudo) {
var m = new google.maps.Marker({
map: map,
animation: google.maps.Animation.DROP,
title: titulo,
position: posicao,
html: conteudo
});
google.maps.event.addListener(m, 'click', function () {
info_window.setContent(this.html);
info_window.open(map, this);
});
}
var map;
var infowindow;
...
function createMarker(...) {
var marker = new google.maps.Marker({...});
google.maps.event.addListener(marker, 'click', function() {
...
if (infowindow) {
infowindow.close();
};
infowindow = new google.maps.InfoWindow({
content: contentString,
maxWidth: 300
});
infowindow.open(map, marker);
}
...
function initialize() {
...
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
...
google.maps.event.addListener(map, 'click', function(event) {
if (infowindow) {
infowindow.close();
};
...
}
}
How about -
google.maps.event.addListener(yourMarker, 'mouseover', function () {
yourInfoWindow.open(yourMap, yourMarker);
});
google.maps.event.addListener(yourMarker, 'mouseout', function () {
yourInfoWindow.open(yourMap, yourMarker);
});
Then you can just hover over it and it will close itself.
I stored a variable at the top to keep track of which info window is currently open, see below.
var currentInfoWin = null;
google.maps.event.addListener(markers[counter], 'click', function() {
if (currentInfoWin !== null) {
currentInfoWin.close(map, this);
}
this.infoWin.open(map, this);
currentInfoWin = this.infoWin;
});
Here is what I used if you are using many markers in a for loop (Django here). You can set an index on each marker and set that index every time you open a window. Closing the previously saved index:
markers = Array();
infoWindows = Array();
var prev_infowindow =false;
{% for obj in objects %}
var contentString = 'your content'
var infowindow = new google.maps.InfoWindow({
content: contentString,
});
var marker = new google.maps.Marker({
position: {lat: {{ obj.lat }}, lng: {{ obj.lon }}},
map: map,
title: '{{ obj.name }}',
infoWindowIndex : {{ forloop.counter0 }}
});
google.maps.event.addListener(marker, 'click',
function(event)
{
if( prev_infowindow ) {
infoWindows[prev_infowindow].close();
}
prev_infowindow = this.infoWindowIndex;
infoWindows[this.infoWindowIndex].open(map, this);
}
);
infoWindows.push(infowindow);
markers.push(marker);
{% endfor %}
var contentString = "Location: " + results[1].formatted_address;
google.maps.event.addListener(marker,'click', (function(){
infowindow.close();
infowindow = new google.maps.InfoWindow({
content: contentString
});
infowindow.open(map, marker);
}));