Angular Google Maps idle event fires multiple times - angularjs

I am using angular-google-maps v-2.3.3. I am loading markers using the "markers" directive and using map "idle" event for some manipulations. My problem is, Every time when the user zoom in or zoom out or pan the map, "idle" event is getting fired n number of times based on the number of markers with in the bounds. For eg: If there are 40 markers, The idle event is getting called 40 times instead of once. Below is my code where I am setting up the idle event.
angular.extend(vm, {
map: {
center: { latitude: 47, longitude: 2 },
markersControl: {},
mapControl: {},
events: {
tilesloaded: function(map) {
$scope.$apply(function() {
vm.mapInstance = map;
});
var map = vm.map.mapControl.getGMap();
$timeout(function() {
google.maps.event.trigger(map, 'resize');
}, 100);
},
dragend: dragend,
idle: function() {
try {
var markers = vm.map.markersControl.getGMarkers();
var map = vm.map.mapControl.getGMap();
for (var i = 0; i < markers.length; i++) {
if (map.getBounds().contains(markers[i].getPosition())) {
markers[i].setVisible(true);
} else {
markers[i].setVisible(false);
}
}
} catch (err) {
// Handle error(s) here
}
}
},
window: {
closeClick: function() {
var markers = vm.map.markersControl.getGMarkers();
markers.forEach(function(v, i) {
v.setAnimation(null);
});
}
}
}
});

Related

Execute an Angular function only if the current tab is active in the browser

I have an angular js function which should be called for every 2 seconds only when the current tab is open in the browser. Is there any way to check whether the current page is active in the browser.
$scope.callAtInterval = function() {
var url = "http://127.0.0.1/test";
$http.get(url).success( function(response) {
$scope.initial = response;
},
function errorCallback(response) {
$scope.result=response;
});
}
$interval( function(){ $scope.callAtInterval(); }, 5000);
}
I think below piece of code is self-explanatory
import { HostListener} from "#angular/core";
#HostListener("window:visibilitychange", ["$event"])
onVisibilityChange($event) {
const isVisible = $event.target.visibilityState === 'visible';
this.logger.info(isVisible);
if (isVisible) {
// tab is visible
} else {
// tab is not-visible
}
}
You would use the focus and blur events of the window:
$(window).on("blur focus", function(e) {
var prevType = $(this).data("prevType");
if (prevType != e.type) { // reduce double fire issues
switch (e.type) {
case "blur":
// cancel your interval function
break;
case "focus":
// emit your interval function
break;
}
}
$(this).data("prevType", e.type);
})

Backbone Modal with Q.promise issue

We have a method (onOpenNotitiesClicked) for showing a Modal view for entering notes. We have implemented the Backbone Modal plugin for this (https://github.com/awkward/backbone.modal).
There are two situations:
There are not yet notes in the backend: initialize and render the
modal
There are already notes in the backend => first collect them and
then pass the notes to the modal (initialize) and then render
In the first situation it works fine! The modal is shown.
In the second situation, the modal is not shown.
I have debugged both situations and in both situations, alle methods are executed and in the elements, I see the HTML of the modal view.
I suspect this looses some data during the Q/promise data get, but I can't see what/where/how/why....
Anyone any idea what I am doing wrong? Or what I am missing?
The creation of the modal:
onOpenNotitieClicked: function (event) {
var $element, taak, taakId, id, options = {};
$element = this.$(event.currentTarget).closest("li");
id = $element.data("id");
taakId = $element.data("taak-id");
taak = this.getCurrentTask(event);
options.taakKey = id;
options.taakId = taakId;
options.heeftNotities = taak.heeftNotities;
options.datacontroller = this.datacontroller;
this.notitiesOptions = options;
// this.renderNotitieModal(options);
if (taak.heeftNotities) {
this.getActiviteitNotities(taakId).then(_.bind(this.onSuccessGetNotities, this), _.bind(this.onErrorGetNotities, this));
} else {
this.renderNotitieModal(this.notitiesOptions);
}
},
In case there are notes to be collected:
getActiviteitNotities: function (taakId) {
return this.datacontroller.getNotities(taakId);
},
onSuccessGetNotities: function (notities) {
this.notitiesOptions.notities = notities;
this.renderNotitieModal(this.notitiesOptions);
},
onErrorGetNotities: function () {
this.renderNotitieModal(this.notitiesOptions);
},
To get the notes from the backend, Q/promises is used.
getNotities: function (taakId, refresh, klantorderId) {
return Q.promise(function (resolve, reject) {
var options = {};
if (!this.notitiesCollection || this.taakId !== taakId || refresh) {
delete this.notitiesCollection;
this.notitiesCollection = this.createCollection("NotitiesCollection", {
id: this.taakId,
resource: this.NOTITIES_RESOURCE
});
if (taakId) {
this.taakId = taakId;
options = {
data: {
parentId: this.taakId
}
};
} else if (klantorderId) {
options = {
data: {
klantorderId: klantorderId
}
};
}
resolve(this.notitiesCollection.fetch(options));
} else if (this.notitiesCollection) {
resolve(this.notitiesCollection.toJSON());
} else {
reject("ERROR");
}
}.bind(this));
},
Notities.js (the modal view):
(function () {
"use strict";
App.Bewaking.modals.BewakingNotitieModal = Backbone.Modal.extend({
template: JST.bewaking_notitie_modal, //jshint ignore:line
title: "Notities",
formatter: new App.Main.helpers.Formatter(),
events: {
"click #save-notitie": "onSaveNotitieClicked"
},
initialize: function (options) {
this.taakId = options.taakId;
this.taakKey = options.taakKey;
this.datacontroller = options.datacontroller;
this.notities = options.notities;
},
afterRender: function () {
console.log("afterRender");
this.$notitieModal = this.$("#notitieModal");
this.$nieuweNotitie = this.$("#nieuwe-notitie");
this.$notitieErrorTekst = this.$("#notitie-error-tekst");
this.$notitieModal.on("shown.bs.modal", function () {
this.$nieuweNotitie.focus();
}.bind(this));
},
render: function () {
console.log(this.notities);
this.$el.html(this.template({
formatter: this.formatter,
notities: this.notities
}));
return this;
}
});
}());

Undefined LatLng google map in AngularJs Controller

I want to retrieve the longitude and latitude position of my click mouse event, but i can't, it gives me Undefined. Any one can help me please ?
I'm using AngularJS and I found that we can do
google.maps.event.addListener(map, 'click', function(event) {
console.log(event.latLng);
});
But I can't do so in my controller it gives me an error, or maybe i don't know how to use that!!
here is my code :
$scope.map = {
center: {
latitude: 36,
longitude: -80
},
events: {
"click": function (event) {
console.log(event.latLng);
}
}
}
and I tried that too but it gives me (Nan,Nan)
$scope.map = {
center: {
latitude: 36,
longitude: -80
},
events: {
"click": function (event) {
var pos = new google.maps.LatLng(event.latLng, event.latLng);
console.log("position: " + pos);
}
}
}
I could solve it like that
events: {
tilesloaded: function (map, eventName, originalEventArgs) {
//map is trueley ready then this callback is hit
},
click: function (mapModel, eventName, originalEventArgs) {
var e = originalEventArgs[0];
var lat = e.latLng.lat(),lon = e.latLng.lng();
console.log("lat long: "lat, lon);
$scope.$apply();
}
}

Refreshing map and markers with angular-google-maps

Hi I am using the angular-google-maps for my project. The html and js code is as follows
html:
<ui-gmap-markers models="apartments" coords="'loc'" icon="'assets/images/map_icon_normal.png'" idkey="'_id'"
fit="'false'" click="click">
<ui-gmap-windows show="'show'" >
<div ng-non-bindable>{{streetAddress}}</div>
</ui-gmap-windows>
</ui-gmap-markers>
</ui-gmap-google-map>
Script:
angular.module('myApp')
.controller('MapCtrl',
function ($scope, $routeParams, Map, uiGmapGoogleMapApi) {
$scope.apartments = [];
$scope.customIcon = "../../assets/images/map_icon_normal.png"
$scope.map = {
center: {
latitude: $routeParams.lat,
longitude: $routeParams.lon
},
zoom: 5,
bounds: {},
events: {
tilesloaded: function (map) {
//console.log('tiles loaded');
$scope.$apply(function () {
$scope.mapInstance = map;
//console.log(map.getBounds().getNorthEast());
$scope.searchbox.options.bounds = new google.maps.LatLngBounds($scope.mapInstance.getBounds().getNorthEast(),
$scope.mapInstance.getBounds().getSouthWest());
});
},
idle: function(map) {
$scope.map.refresh = false;
},
resize: function(map) {
console.log('resize');
},
dragend: function() {
}
},
markersEvents: {
click: function(marker, eventName, model, args) {
console.log('markerEvent click');
$scope.map.window.model = model;
$scope.map.window.show = true;
}
},
window : {
marker: {},
show: false,
closeClick: function() {
this.show = false;
},
options: {} // define when map is ready
},
control: {},
refresh: function () {
$scope.map.control.refresh();
}
}
uiGmapGoogleMapApi.then(function (map) {
$scope.getData(20, 0, map);
map.visualRefresh = true;
$scope.mapInstance = map;
})
$scope.getData = function(limit, offset, map) {
Map.getApartments($routeParams.lat, $routeParams.lon, limit, offset).success(function (data) {
///----- I get undefined error here---
$scope.map.control.refresh();
});
}})
}
I am not sure how to refresh the map with the new markers or even trigger an update to the map. I played around with 'control' and 'refresh' params of the ui-gmap-google-map but cannot get it to work.
You need to use uiGmapIsReady --- not uiGmapGoogleMapApi --- to wait for control objects to be augmented with their methods (such as refresh).
The uiGmapIsReady service provides a promise which resolves when all uiGmapGoogleMap directives have been fully initialized, while the uiGmapGoogleMapApi service resolves simply when the Google Maps JS API has loaded.
See this answer for an example of using uiGmapIsReady. And of course, don't forget the docs.
Regarding how to get updates to your models property on the scope to cause updates to your map, your code example needs to be fleshed out and cleaned up to help you there. (For example, what is the resolution of getApartments doing to update $scope.apartments? Or maybe asking that question is itself the answer?) Take a look at this fiddle, it might help you in the meantime.
Try dorebuildall attribute.
<ui-gmap-markers
models="apartments"
coords="'loc'"
icon="'assets/images/map_icon_normal.png'"
idkey="'_id'"
fit="'false'"
click="click"
dorebuildall="true">
<ui-gmap-windows></ui-gmap-windows>
</ui-gmap-markers>
More details at: http://angular-ui.github.io/angular-google-maps/

With Angular update the scope from an event handler

I am having one issue I was hoping someone would help me on. I am using Angular and the angular google maps directive. I have an event handler registered on idle so that I want to update what markers are shown but when the event is handled it returns the map and I've lost scope so I am unsure how to add new markers onto the map?
I setup a map like so:
<google-map center="map.center" zoom="map.zoom" events="map.events"> <markers> <marker ng-repeat="marker in map.markers" coords="marker"> </marker> </markers> </google-map>
That then uses the following to setup its initial values on events:
$scope.map = {
center: {
latitude: 45,
longitude: -73
},
zoom: 8,
events:{
idle:getJobs
},
markers:[]
};
When the event fires the getJobs function I have lost the scope so cannot push new markers onto the map with angular, any ideas??
function getJobs($scope) {
self = this;
JobService.getJobs(self.map).then(function(jobData){
for (var i = 0; i < jobData.length; i++) {
var job = jobData[i];
if (job.get('location') != null && job.get('location').longitude != null) {
$scope.map.markers.push(createJobMarker(job.get('role'),job.get('location').longitude,job.get('location').latitude),i);
}
}
});
}
Try
function getJobs($scope) {
self = this;
JobService.getJobs(self.map).then(function(jobData){
$scope.apply(function () {
for (var i = 0; i < jobData.length; i++) {
var job = jobData[i];
if (job.get('location') != null && job.get('location').longitude != null) {
$scope.map.markers.push(createJobMarker(job.get('role'),job.get('location').longitude,job.get('location').latitude),i);
}
}
});
});
}
Update:
I see, you are just losing reference to the scope variable. Try setting up your event like this:
$scope.map = {
center: {
latitude: 45,
longitude: -73
},
zoom: 8,
events:{
idle: function () {
getJobs($scope);
}
},
markers:[]
};

Resources