Weird behavior of angular-google-maps in Safari - angularjs

Im using this project (http://angular-google-maps.org/#!/) to work with AngularJS. My code seems like:
app.js
function ( $scope, markerService ) {
var markerCollection = [];
angular.extend($scope, {
map: {
control: {},
center: {
latitude: 33.5,
longitude: -112
},
zoom: 10,
fit: true,
visible: true,
pan: true,
options: {
navigationControl: true,
scaleControl: true
}
}
});
var setMapMarkers = function (){
var markers = {};
var index = 0;
angular.forEach($scope.services, function (key) {
var service = key.address;
markerCollection.push(service);
var serviceId = service.service.id;
markers[index] = {
"latitude": parseFloat(service.latitude),
"longitude": parseFloat(service.longitude)
};
index++;
});
$scope.markers = markers;
};
setMapMarkers();
}
Im getting this behavior in Safari and its a very weird.
https://www.dropbox.com/s/r7iwlr9mnboem1d/MapGrab.mov?dl=0
Someone maybe know what can be the problem?

Related

How to access variable in angular scope?

When I insert console.log($scope) into my code, I get the following result:
$get.k.$new.a.$$childScopeClass.$$childScopeClass {$$childTail: null, $$childHead: null, $$nextSibling: null, $$watchers: Array[4], $$listeners: Object…}
$$childHead: null
$$childScopeClass: null
$$childTail: null
$$listenerCount: Object
$$listeners: Object
$$nextSibling: null
$$prevSibling: $get.k.$new.a.$$childScopeClass.$$childScopeClass
$$watchers: Array[4]
$id: "005"
$parent: Object
Bad: false
Good: true
Search: function () {
address: "63146"
focus: "63146"
this: $get.k.$new.a.$$childScopeClass.$$childScopeClass
__proto__: Object
The variable I am interested in is Good: true. However, when I call console.log($scope.Good) on the next line, it returns false.
How do I call the above "Good" variable that returns true in the console?
edit:
Controller
app.controller('locationController', function ($scope) {
$scope.Good = false;
$scope.Bad = false;
var mapOptions = {
center: { lat: 38.68, lng: -90.46 },
zoom: 8
};
var image = {
url: 'app/assets/img/marker.png'
}
var map = new google.maps.Map(document.getElementById('map'),
mapOptions);
$scope.Search = function () {
$scope.Good = false;
$scope.Bad = false;
var address = $scope.address;
var radius = parseInt(50, 10) * 1000;
var marker_start = new google.maps.Marker({
position: { lat: 38.688757, lng: -90.464391 },
map: map,
icon: image,
title: ""
});
var fill = '#fff';
var populationOptions = {
strokeColor: '#66FF99',
strokeOpacity: 0.2,
strokeWeight: 2,
fillColor: fill,
fillOpacity: 0.35,
map: map,
center: new google.maps.LatLng(38.68, -90.46),
radius: 80000
};
var lat = '';
var lng = '';
var geocoder = new google.maps.Geocoder();
var marker_user = null;
geocoder.geocode({ 'address': address }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
lat = results[0].geometry.location.lat();
lng = results[0].geometry.location.lng();
marker_user = new google.maps.Marker({
position: { lat: lat, lng: lng },
map: map,
animation: google.maps.Animation.DROP,
title: "Your Location"
});
if (google.maps.geometry.spherical.computeDistanceBetween(marker_user.getPosition(), marker_start.getPosition()) < 80000)
$scope.$apply(function () { $scope.Good = true; });
else
$scope.$apply(function () { $scope.Bad = true; });
}
});
console.log($scope);
console.log($scope.Good);
console.log($scope.Bad);
var cityCircle = new google.maps.Circle(populationOptions);
};
});
Good becomes true only after the callback function passed to geocoder.geocode() has been called. But you're printing it before it has been called, right after having asked the geocoder to geocode.
ask the geocoder to geocode. This sends an HTTP request to Google
print Good: it's still false
when the response from Google comes in, the callback is executed and Good becomes true

AngularJS Ionic Leaflet - Map markers not showing

So Ive been trying to get leaflet working in an Ionic app and everything is working fine except my markers. They are not being shown in the default screen nor the locate() function. below is my code
html snippet
<leaflet defaults="map.defaults" center="map.center" markers="map.markers" ng-if="map"></leaflet>
controller
app.controller('MapController',function($scope, $cordovaGeolocation, $stateParams) {
$scope.$on("$stateChangeSuccess", function() {
$scope.map = {
defaults: {
tileLayer: 'http://{s}.tile.osm.org/{z}/{x}/{y}.png',
maxZoom: 18,
zoomControlPosition: 'bottomleft'},
center: {
lat : 20.6219444444,
lng : -105.228333333,
zoom : 15},
markers: {
lat : 20.6219444444,
lng : -105.228333333,
message: "Puerto Vallarta, MX",
focus: true,
draggable: false}
};
});
$scope.locate = function(){
$cordovaGeolocation
.getCurrentPosition()
.then(function (position) {
$scope.map.center.lat = position.coords.latitude;
$scope.map.center.lng = position.coords.longitude;
$scope.map.center.zoom = 16;
$scope.map.markers.now = {
lat:position.coords.latitude,
lng:position.coords.longitude,
message: "You Are Here",
focus: true,
draggable: false
};
}, function(err) {
// error
console.log("Location error!");
console.log(err);
});
};
});
any ideas?? thanks for looking
SOLVED
I added marker value to a variable and then copied that into the $scope.map
here is the updated working controller
app.controller('MapController',function($scope, $cordovaGeolocation, $stateParams) {
$scope.$on("$stateChangeSuccess", function() {
var mainMarker = {
lat: 20.6219444444,
lng: -105.228333333,
focus: true,
message: "Puerto Vallarta, MX",
draggable: false};
$scope.map = {
defaults: {
tileLayer: 'http://{s}.tile.osm.org/{z}/{x}/{y}.png',
maxZoom: 18,
zoomControlPosition: 'bottomleft'},
center: {
lat : 20.6219444444,
lng : -105.228333333,
zoom : 15},
markers: {
mainMarker: angular.copy(mainMarker)}
};
});
$scope.locate = function(){
$cordovaGeolocation
.getCurrentPosition()
.then(function (position) {
$scope.map.center.lat = position.coords.latitude;
$scope.map.center.lng = position.coords.longitude;
$scope.map.center.zoom = 16;
$scope.map.markers.now = {
lat:position.coords.latitude,
lng:position.coords.longitude,
message: "You Are Here",
focus: true,
draggable: false
};
}, function(err) {
// error
console.log("Location error!");
console.log(err);
});
};
});

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();
}
}

How to redraw flot chart in angularjs?

I am using flot chart Angularjs directive to draw a stacked bar chart. When I make a async call to an end point to fetch data for chart, it is unable show up. I suspect it needs to redraw. There is a draw() function which looks like re draws flot chart. Please help me re-draw my flot chart in Angularjs.
<flot dataset="tasksRunData" options="tasksRunChartOptions" class="center-block" width="100%" height="400px" id="reportTasksRunRange.id"></flot>
angular.module('myApp').controller('Step2Controller', function($scope, $location, $interval, dialogs, $modal, $transition, ReportingService) {
...
$scope.tasksRunData = mainArray;
$scope.tasksRunChartOptions = {
legend: {
show: true,
margin: 2
},
xaxis: {
ticks: yaxisArray,
alignTicksWithAxis: "right"
},
grid: {
labelMargin: 10,
hoverable: true,
borderWidth: 0
},
series: {
stack: true
},
colors: colorCodesArray,
tooltip: true
};
...
$scope.redrawTasksRunDataHistoByChart();
...
$scope.redrawTasksRunDataHistoByChart = function() {
$scope.tasksRunData.draw(); //TypeError: undefined is not a function
alert("AAAA");
}
});
Update
ReportService.getTasksRunDateHistoByType().then(function(result) {
$scope.renderTasksRunDateHistoByType(result);
});
$scope.renderTasksRunDateHistoByType = function(jsonInput) {
console.log(json[RUN_AGG_BY_DATE_HISTO].aggregations[TASK_TYPE_AGG].buckets);
var yaxis = [];
var buckets = json[RUN_AGG_BY_DATE_HISTO].aggregations[TASK_TYPE_AGG].buckets;
var log = [];
var mainArray = [];
var colorCodes = ["#5C832F","#7B52AB","#263248","#AB1A25","#FF8598","#AB1A25","#FEB41C","#193441","#193441","#BEEB9F","#E3DB9A","#917A56"],
idx = 0;
angular.forEach(buckets, function(value, key) {
this.push(key + ': ' + value +", "+value["key"]);
var dataArray = [], index = 0;
console.log(JSON.stringify(value[RUN_OVER_TIME_KEY]["buckets"]));
angular.forEach(value[RUN_OVER_TIME_KEY]["buckets"], function(value, key) {
var dataArr = [];
dataArr.push('['+index+', '+value["doc_count"]+']');
dataArray.push(dataArr);
yaxis.push(JSON.parse('['+index+', "'+$scope.translate(value["key"])+'", "'+value["key"]+'"]'));
index++;
}, log);
var barObject = '"bars": {"show": "true", "barWidth":0.8, "fillColor": "'+colorCodes[idx]+'", "order": 1, "align": "center"}';
var object = '{ "data": ['+dataArray+'], "label": "'+value["key"]+'", '+barObject+'}';
mainArray.push(JSON.parse(object));
idx++;
}, log);
console.log(yaxis);
$scope.tasksRunData = mainArray;
$scope.tasksRunChartOptions = {
legend: {
show: true,
margin: 2
},
xaxis: {
//ticks:[[0,'Oct 4'],[1,'Oct 5'],[2,'Oct 6'],[3,'Oct 7'],[4,'Oct 8'],[5,'Oct 9']],
ticks: yaxis,
alignTicksWithAxis: "right"
},
grid: {
labelMargin: 10,
hoverable: true,
borderWidth: 0
},
series: {
stack: true
},
colors: colorCodes,
tooltip: true
};
};
angularjs service
angular.module('myApp')
.service('ReportService', function ReportService($http, $q) {
var getTasksRunDateHistoByType = function() {
var deferred = $q.defer();
$http({
method: 'POST',
url: "http://localhost:4040/reports/taskRun",
data: '{ "client_user_info": { "client_id": "MU03"}}'
}).
success(function(result, status, headers, config) {
deferred.resolve(result);
}).
error(function(result, status, headers, config) {
console.log("Error");
});
return deferred.promise;
};
return {
getTasksRunDateHistoByType: getTasksRunDateHistoByType
};
});
Looking at the source code to the directive, it'll redraw automatically when $scope.dataset changes.
$scope.redrawChart = function() {
var tmp = [];
for (var i = 0; i < 10; i++){
tmp.push([i,Math.random() * 10]);
}
$scope.dataset = [{ data: tmp }];
};
Here's an example.
EDITS FOR UPDATES
I'm having a hard time following your code, but in the end, you'll end up in the $scope.renderTasksRunDateHistoByType with data in the variable jsonInput. You then store some variable mainArray (which doesn't exist as far as I can tell) into other $scope level variables. I never see you assign data back to $scope.dataset. This is what the flot directive is watching to trigger a redraw. It's just that simple.
$scope.renderTasksRunDateHistoByType = function(jsonInput) {
$scope.dataset = [{
data: jsonInput
}];
//console.log(jsonInput);
//$scope.tasksRunData = mainArray;
//$scope.tasksRunChartOptions
//getting data here once response is received from server
};
See updates here.

angular-google-maps center zoom multiple markers

I'm using AngularJS for Google Maps and want to dynamically center and zoom a map based on multiple markers that are dynamically loaded. This is for a Cordova app using the Ionic Framework.
Here's my view:
<ion-view title="" ng-controller="MapCtrl as vm">
<ion-content class="padding">
<google-map id="mainMap" control="vm.googleMap" draggable="true" center="vm.map.center" zoom="vm.map.zoom" mark-click="false">
<markers idKey="mainMap" fit="vm.map.fit">
<marker idKey="marker.id" ng-repeat="marker in vm.map.markers" coords="marker.coords" options="marker.options">
<marker-label content="marker.name" anchor="2 0" class="marker-labels"/>
</marker>
</markers>
</google-map>
</ion-content>
</ion-view>
Here's my controller:
angular.module('myApp.controllers', [])
.controller('MapCtrl', function($scope, $ionicPlatform) {
var vm = this;
vm.googleMap = {}; // this is filled when google map is initialized, but it's too late
vm.mapMarkers = [];
vm.arrMarkers = [
{
id: "home",
name: "home",
coords: {
latitude:xxxxxxx, //valid coords
longitude:xxxxxxx //valid coords
},
options: {
animation: google.maps.Animation.BOUNCE
}
},
{
id: "placeAId",
name: "Place A",
coords: {
latitude:xxxxxxx, //valid coords
longitude:xxxxxxx //valid coords
}
},
{
id: "placeBId",
name: "Place B",
coords: {
latitude:xxxxxxx, //valid coords
longitude:xxxxxxx //valid coords
}
}
];
vm.map = {
center: { //how to determine where to center???
latitude: xxxxxxx, //valid coords
longitude: xxxxxxx //valid coords
},
zoom: 12, //how to determine zoom dynamically???
fit: true,
markers: vm.arrMarkers
};
var setMapBounds = function () {
var bounds = new google.maps.LatLngBounds();
createMarkers();
var markers = vm.mapMarkers;
for(var i=0; i<markers.length; i++) {
bounds.extend(markers[i].getPosition());
}
var map = vm.googleMap.control.getGMap();
map.setCenter(bounds.getCenter());
map.fitBounds(bounds);
//remove one zoom level to ensure no marker is on the edge.
map.setZoom(map.getZoom()-1);
// set a minimum zoom
// if you got only 1 marker or all markers are on the same address map will be zoomed too much.
if(map.getZoom()> 15){
map.setZoom(15);
}
};
var createMarkers = function() {
var map = vm.googleMap.control.getGMap(); //vm.googleMap.control is undefined because this fire before map is initialized
angular.forEach(vm.restaurants, function(restaurant, index) {
var marker = new google.maps.Marker({
map: map,
position: new google.maps.LatLng(restaurant.coords.latitude, restaurant.coords.longitude),
title: restaurant.name
});
vm.mapMarkers.push(marker);
});
};
$ionicPlatform.ready(function() {
setMapBounds();
});
})
So, my question is how do I center and zoom the map using multiple dynamically loaded markers? Also, how do I get an instance of googleMap.control (vm.googleMap.control) before the map is loaded?
Here's my code just in case anyone was wondering how to do this locally. This is a simple solution for what I needed and my indeed go back to angualr-google maps, but as of now this works fine in my application.
angular.module('myApp.controllers', [])
.controller('MapCtrl', function($scope) {
var vm = this;
vm.googleMap = null;
vm.mapMarkers = [];
var onSuccess = function(position) {
vm.userLocation.coords.latitude = position.coords.latitude;
vm.userLocation.coords.longitude = position.coords.longitude;
initializeMap();
};
var onError = function(error) {
alert('code: ' + error.code + '\n' + 'message: ' + error.message);
};
vm.userLocation = {
id: "home",
title: "home",
coords: {
latitude: 33.636727,
longitude: -83.920702
},
options: {
animation: google.maps.Animation.BOUNCE
}
};
vm.places = [
{
id: "78869C43-C694-40A5-97A0-5E709AA6CE51",
title: "Place A",
coords: {
latitude: 33.625296,
longitude: -83.976206
}
},
{
id: "52319278-83AA-46D4-ABA6-307EAF820E77",
title: "Place B",
coords: {
latitude: 33.576522,
longitude: -83.964981
}
}
];
var addMarkers = function() {
var userLocation = new google.maps.Marker({
map: vm.googleMap,
position: new google.maps.LatLng(vm.userLocation.coords.latitude, vm.userLocation.coords.longitude),
//animation: vm.userLocation.options.animation,
title: vm.userLocation.title
});
vm.mapMarkers.push(userLocation);
angular.forEach(vm.places, function(location, index) {
var marker = new google.maps.Marker({
map: vm.googleMap,
position: new google.maps.LatLng(location.coords.latitude, location.coords.longitude),
title: location.title
});
vm.mapMarkers.push(marker);
});
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < vm.mapMarkers.length; i++) {
bounds.extend(vm.mapMarkers[i].getPosition());
}
vm.googleMap.setCenter(bounds.getCenter());
vm.googleMap.fitBounds(bounds);
//remove one zoom level to ensure no marker is on the edge.
vm.googleMap.setZoom(vm.googleMap.getZoom() - 1);
// set a minimum zoom
// if you got only 1 marker or all markers are on the same address map will be zoomed too much.
if (vm.googleMap.getZoom() > 15) {
vm.googleMap.setZoom(15);
}
};
var initializeMap = function() {
var mapOptions = {
mapTypeId: google.maps.MapTypeId.ROADMAP,
zoom: 12,
center: new google.maps.LatLng(vm.userLocation.coords.latitude, vm.userLocation.coords.longitude)
};
var div = document.getElementById("map_canvas");
//var map = plugin.google.maps.Map.getMap(div, mapOptions);
vm.googleMap = new google.maps.Map(div, mapOptions);
addMarkers();
var width = screen.width;
var height = screen.height;
};
navigator.geolocation.getCurrentPosition(onSuccess, onError);
})
Your previous answer is good but doesn't include usage of the google maps directives you mentioned in the begining of the post. There is a way to do it using those directives, here is how:
Assuming we are in the directive's scope
Define scope.mapControl = {}; - this will have new access methods for map and markers
When defining your markup for the directives - for map and marker - include this control attribute to be added:
<ui-gmap-google-map center='map.center' zoom='map.zoom' control="mapControl">
<ui-gmap-marker ng-repeat="location in locations" coords="location.coordinates" options="location.markerOptions" idkey="location.id" control="mapControl">
<ui-gmap-window options="location.markerWindowOptions" closeclick="closeMarkerWindow(location.id)" show="true">
<div>{{location.description}}</div>
</ui-gmap-window>
</ui-gmap-marker>
</ui-gmap-google-map>
In your directive's event or some method:
var map = scope.mapControl.getGMap();
var markers = scope.mapControl.getGMarkers();
var bounds = map.getBounds();
for (var i = 0; i < markers.length; i++) {
bounds.extend(markers[i].getPosition());
}
map.setCenter(bounds.getCenter());
map.fitBounds(bounds);
map.setZoom(map.getZoom() - 1);

Resources