I want to achieve something similar to this http://jsfiddle.net/sya8gn0w/1/.
Now the problem is I have my own custom directive to display map. I want a function in child controller which will achieve above mentioned functionality on some button click.
eg. The place marker functionality triggers only if I click on some button.
Present code -
function ParentCtrl($scope){
var mainCtrl = this;
angular.extend(mainCtrl , {
map: {
center: {
latitude: 18.5,
longitude: 73.85
},
zoom: 13,
markers: [],
events: {
click: function (map, eventName, originalEventArgs) {
var e = originalEventArgs[0];
var lat = e.latLng.lat(), lon = e.latLng.lng();
var marker = {
id: Date.now(),
coords: {
latitude: lat,
longitude: lon
}
};
mainCtrl .map.markers.pop();
mainCtrl .map.markers.push(marker);
console.log(mainCtrl .map.markers);
console.log("latitude : "+lat+" longitude : "+lon);
$scope.$apply();
}
}
}
});
};
I want to move the functionality present in 'click:' part of angular.extend to a function presents in ChildCtrl controller. Is it possible ?
Ortherwise suggest me different approach to achieve this.
I don't know whether my answer going to help you or not.
Recently I worked on GoogleMap, I want to share what I know.
angular.extend(scope, {
map: {
show: true,
control: {},
version: 'uknown',
center: {
latitude: 0,
longitude: 0
},
options: {
streetViewControl: false,
panControl: false,
maxZoom: 10,
minZoom: 1
},
zoom: 2,
dragging: false,
bounds: {},
markers: scope.markers,
doClusterMarkers: true,
currentClusterType: 'standard',
clusterTypes: clusterTypes,
selectedClusterTypes: selectedClusterTypes,
clusterOptions: selectedClusterTypes['standard'],
events: {
tilesloaded: function(map, eventName, originalEventArgs) {},
click: function(mapModel, eventName, originalEventArgs) {},
dragend: function() {}
},
toggleColor: function(color) {
if (color === 'red') {
return '#6060FB';
} else {
return 'red';
}
}
}
Here the statement markers: scope.markers will help to create new markers or to remove old markers.
In "ChildCtrl" you write a function to update scope.markers object of parent controller.
You could declare the function for adding a marker in a separate controller
and then utilize $controller service to inject that controller into another controller:
angular.module('main', ['uiGmapgoogle-maps'])
.controller('MapCtrl', function ($scope,$controller) {
$controller('MarkerCtrl', {$scope: $scope});
angular.extend($scope, {
map: {
center: {
latitude: 42.3349940452867,
longitude:-71.0353168884369
},
zoom: 11,
markers: [],
events: {
click: function (map, eventName, originalEventArgs) {
var e = originalEventArgs[0];
$scope.addMarker(e.latLng);
$scope.$apply();
}
}
}
});
})
.controller('MarkerCtrl', function($scope) {
angular.extend($scope, {
addMarker: function(latLng) {
var marker = {
id: Date.now(),
coords: {
latitude: latLng.lat(),
longitude: latLng.lng()
}
};
$scope.map.markers.push(marker);
}
});
});
Plunker
I used different but better approach to achieve the desired results.
Found this solution on fiddle . Hope this would be helpful for someone else also.
function dragMarkerService(resolveAddressService){
this.placeMarker = function(location, idValue, map){
var myMarker = new google.maps.Marker({
position: new google.maps.LatLng(location.latitude, location.longitude),
draggable: true
});
google.maps.event.addListener(myMarker, 'dragend', function (evt) {
location.latitude = evt.latLng.lat();
location.longitude = evt.latLng.lng();
resolveAddressService.resolveAddress(location, idValue)
});
google.maps.event.addListener(myMarker, 'dragstart', function (evt) {
angular.element(idValue).val() = 'Currently dragging marker...';
});
map.setCenter(myMarker.position);
myMarker.setMap(map);
}
};
Related
I am making a vue project and I want to use leaflet inside of my components. I have the map showing but I run into an error when I try to add a marker to the map. I get
Uncaught TypeError: events.forEach is not a function
at VueComponent.addEvents (VM2537 Map.vue:35)
at e.boundFn (VM2533 vue.esm.js:191)
at HTMLAnchorElement. (leaflet.contextmenu.js:328)
at HTMLAnchorElement.r (leaflet.js:5)
<template>
<div>
<div id="map" class="map" style="height: 781px;"></div>
</div>
</template>
<script>
export default {
data() {
return {
map: [],
markers: null
};
},
computed: {
events() {
return this.$store.state.events;
}
},
watch: {
events(val) {
this.removeEvents();
this.addEvents(val);
}
},
methods: {
addEvents(events) {
const map = this.map;
const markers = L.markerClusterGroup();
const store = this.$store;
events.forEach(event => {
let marker = L.marker(e.latlng, { draggable: true })
.on("click", el => {
store.commit("locationsMap_center", e.latlng);
})
//.bindPopup(`<b> ${event.id} </b> ${event.name}`)
.addTo(this.map);
markers.addLayer(marker);
});
map.addLayer(markers);
this.markers = markers;
},
removeEvent() {
this.map.removeLayer(this.markers);
this.markers = null;
}
},
mounted() {
const map = L.map("map", {
contextmenu: true,
contextmenuWidth: 140,
contextmenuItems: [
{
text: "Add Event Here",
callback: this.addEvents
}
]
}).setView([0, 0], 1);
L.tileLayer("/static/map/{z}/{x}/{y}.png", {
maxZoom: 4,
minZoom: 3,
continuousWorld: false,
noWrap: true,
crs: L.CRS.Simple
}).addTo(map);
this.map = map;
}
};
</script>
New2Dis,
Here is your example running in a jsfiddle.
computed: {
events: function () {
return this.store.events;
}
},
watch: {
events: function (val) {
this.removeEvents();
this.addEvents(val);
}
},
methods: {
addEvents(events) {
console.log("hoi")
const map = this.map;
const markers = L.markerClusterGroup();
const store = this.$store;
events.forEach(event => {
let marker = L.marker(event.latlng, { draggable: true })
.on("click", el => {
//store.commit("locationsMap_center", event.latlng);
})
.bindPopup(`<b> ${event.id} </b> ${event.name}`)
.addTo(this.map);
markers.addLayer(marker);
});
map.addLayer(markers);
this.markers = markers;
},
removeEvents() {
if (this.markers != null) {
this.map.removeLayer(this.markers);
this.markers = null;
}
}
},
I did replace some things to make it works, like the $store as I don't have it, and removeEvent was not written correctly, so I'm not sure what I actually fixed...
I have also created a plugin to make it easy to use Leaflet with Vue.
You can find it here
You will also find a plugin for Cluster group here
Give it a try and let me know what you think.
I want to show Google map in my html . here is my code:
html:
<div class="map-content">
<div map-marker="" ng-model="searchLocation" class="mapmarker"></div>
</div>
js:
app.directive('mapMarker',function(){
return {
restrict: 'EA',
require: '?ngModel',
scope:{
searchLocation: '=ngModel'
},
controller: function ($scope) {
$scope.searchLocation = {
latitude: 48.137273,
longitude: 11.575251
};
},
resolve: {
load: function () {
}
},
link: function(scope , element, attrs , ngModel){
var mapOptions;
var googleMap;
var searchMarker;
var searchLatLng;
ngModel.$render = function(){
searchLatLng = new google.maps.LatLng(scope.searchLocation.latitude, scope.searchLocation.longitude);
mapOptions = {
center: searchLatLng,
zoom: 12,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
googleMap = new google.maps.Map(element[0],mapOptions);
searchMarker = new google.maps.Marker({
position: searchLatLng,
map: googleMap,
draggable: true
});
google.maps.event.addListener(searchMarker, 'dragend', function(){
scope.$apply(function(){
scope.searchLocation.latitude = searchMarker.getPosition().lat();
scope.searchLocation.longitude = searchMarker.getPosition().lng();
});
}.bind(this));
};
scope.$watch('searchMarker', function(value){
var myPosition = new google.maps.LatLng(scope.searchLocation.latitude, scope.searchLocation.longitude);
searchMarker.setPosition(myPosition);
}, true);
}
}
});
Also, I include
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
It knows script file but it can't show map on my html. Any suggestion?
With a little bit of modifications your example works: see my plunkr.
angular
.module('app', [])
.directive('mapMarker',function(){
return {
restrict: 'EA',
scope:{
searchLocation: '=mapMarker'
},
controller: function ($scope) {
$scope.searchLocation = {
latitude: 48.137273,
longitude: 11.575251
};
},
link: function(scope , element, attrs , ngModel){
var mapOptions;
var googleMap;
var searchMarker;
var searchLatLng;
searchLatLng = new google.maps.LatLng(scope.searchLocation.latitude, scope.searchLocation.longitude);
mapOptions = {
center: searchLatLng,
zoom: 12,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
googleMap = new google.maps.Map(element[0], mapOptions);
searchMarker = new google.maps.Marker({
position: searchLatLng,
map: googleMap,
draggable: true
});
google.maps.event.addListener(searchMarker, 'dragend', function(){
scope.$apply(function(){
scope.searchLocation.latitude = searchMarker.getPosition().lat();
scope.searchLocation.longitude = searchMarker.getPosition().lng();
});
});
scope.$watch('searchMarker', function(value){
var myPosition = new google.maps.LatLng(scope.searchLocation.latitude, scope.searchLocation.longitude);
searchMarker.setPosition(myPosition);
}, true);
}
}
});
You don't need ngModel. Especially ngModel.$render. It is needed for inputs, which is not your case.
Container for map has to have initial size: width and height.
I need to use a "resetMap" function which I defined in my initMap function (callback function for google map), to bind to reset button. Now it cannot be used because its not there in the global scope.
If I move this function to global scope its items such as mapOptions.center setzoom etc will be undefined.
This is my script file
var map;
/* Hardcoding 5 airport locations - our data - model*/
var airports = [
{
title: "Calicut International Airport",
lat: 11.13691,
lng: 75.95098,
streetAddress: "Karipur",
cityAddress: "Malappuram, Kerala",
visible: ko.observable(true),
id: "nav0",
showIt: true
},
{
title: "Chennai International Airport",
lat: 12.9920434,
lng: 80.1631409,
streetAddress: "Meenambakkam",
cityAddress: "Chennai, Tamil Nadu",
visible: ko.observable(true),
id: "nav1",
showIt: true
},
{
title: "Trivandrum International Airport",
lat: 8.4829722,
lng: 76.909139,
streetAddress: "Vallakkadavu",
cityAddress: "Thiruvananthapuram, Kerala",
visible: ko.observable(true),
id: "nav2",
showIt: true
},
{
title: "Cochin International Airport",
lat: 10.15178,
lng: 76.39296,
streetAddress: "Nedumbassery",
cityAddress: "Kochi, Kerala",
visible: ko.observable(true),
id: "nav3",
showIt: true
},
{
title: "Kempegowda International Airport",
lat: 13.2143948,
lng: 77.6896124,
streetAddress: "Devanahalli",
cityAddress: "Bengaluru, Karnataka",
visible: ko.observable(true),
id: "nav4",
showIt: true
}
];
/* Initializing map, markers */
function initMap() {
var myLatlng = new google.maps.LatLng(13.2143948, 77.6896124);
var mapOptions = {
zoom: 6,
disableDefaultUI: true
};
var bounds = new google.maps.LatLngBounds(
new google.maps.LatLng(8.4829722, 76.909139), //SW coordinates here
new google.maps.LatLng(13.2143948, 77.6896124) //NE coordinates here
);
map = new google.maps.Map(document.getElementById("map"), mapOptions);
map.fitBounds(bounds);
setMarkers(airports);
setMapWithMarker();
/* Function to reset the map zoom and set center */
function resetMap() {
map.setCenter(mapOptions.center);
map.setZoom(6);
}
$(window).resize(function(){
map.setCenter(mapOptions.center);
});
}
/* Controlling the visibility of marker based on the 'showIt' property */
function setMapWithMarker() {
for (var i = 0; i < airports.length; i++) {
if(airports[i].showIt === true) {
airports[i].locMarker.setMap(map);
} else {
airports[i].locMarker.setMap(null);
}
}
}
/* Setting markers on map and attaching content to each of their info windows */
function setMarkers(location) {
var img = 'img/airport.png';
for (var i = 0; i < location.length; i++) {
location[i].locMarker = new google.maps.Marker({
position: new google.maps.LatLng(location[i].lat, location[i].lng),
map: map,
animation: google.maps.Animation.DROP,
title: location.title,
icon:img
});
var airportTitle = location[i].title;
var wikiUrl = 'https://en.wikipedia.org/w/api.php?action=opensearch&search=' +
airportTitle + '&format=json&callback=wikiCallback';
(function(i){
var wikiRequestTimeout = setTimeout(function() {
$('.show-error').html('ERROR: Failed to load wikipedia data - Airport details will not show up! Sorry for the inconvenience caused.');
}, 5000);
$.ajax({
url: wikiUrl,
dataType: "jsonp"
}).done(function(response){
var article = response[2][0];
location[i].contentString =
'<strong>'+ location[i].title + '</strong><br><p>' + location[i].streetAddress
+ '<br>' + location[i].cityAddress + '<br></p><p>' + article +
'</p><p>Source: Wikipedia</p>';
clearTimeout(wikiRequestTimeout);
});
})(i);
/* info window initialization and setting content to each marker's info window */
var infowindow = new google.maps.InfoWindow({});
new google.maps.event.addListener(location[i].locMarker, 'click',
(function(airport, i) { return function() {
airport.setAnimation(google.maps.Animation.BOUNCE);
setTimeout(function() {
airport.setAnimation(null);
}, 2400);
infowindow.setContent(location[i].contentString);
infowindow.open(map,this);
map.setZoom(15);
map.setCenter(airport.getPosition());
};
})(location[i].locMarker, i));
/* info window call when clicked on airport menu item */
var searchNav = $('#nav' + i);
searchNav.click((function(airport, i) {
return function() {
airport.setAnimation(google.maps.Animation.BOUNCE);
setTimeout(function() {
airport.setAnimation(null);
}, 2200);
infowindow.setContent(location[i].contentString);
infowindow.open(map,airport);
map.setZoom(15);
map.setCenter(airport.getPosition());
};
})(location[i].locMarker, i));
}
}
/* Function for toggling the menu */
function slideToggle() {
$(this).toggleClass('toggled');
$( "#listing" ).toggle( "slow", function() {
// Animation complete.
});
}
/* Our view model */
function viewModel() {
var self = this;
this.locMarkerSearch = ko.observable('');
ko.computed(function() {
var search = self.locMarkerSearch().toLowerCase();
return ko.utils.arrayFilter(airports, function(airport) {
if (airport.title.toLowerCase().indexOf(search) >= 0) {
airport.showIt = true;
return airport.visible(true);
} else {
airport.showIt = false;
setMapWithMarker();
return airport.visible(false);
}
});
});
};
// Activates knockout.js
ko.applyBindings(new viewModel());
I need to bind the function here in my index.html
<footer>
<button id="reset" data-bind="click: resetMap">Reset Zoom to center</button>
</footer>
<script src="js/lib/knockout-3.4.0.js"></script>
<script src="js/script.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDVOVW9WT7QaVlFYDkE7K2Qm-AvSS02YrM&callback=initMap" async defer onerror="googleError()"></script>
How can I resolve this problem? Thanks in advance..
You haven't shown us how viewModel uses initMap, but fundamentally, initMap needs to make resetMap available to the outside world. One way to do that is to return it:
function initMap() {
// ...
function resetMap() {
}
// ...
return resetMap;
}
and then have code in viewModel put that on the view model:
function viewModel() {
this.resetMap = initMap(); // I assume you're calling this indirectly; whatever
}
Then resetMap has access to what it needs, and it's on the view model so it can be bound.
I got a view where I render a google map which then should check the location of the device periodically.
Controller
.controller('SearchCtrl', function($scope, $ionicLoading, TrackLocation) {
//document.addEventListener("deviceready", onDeviceReady, false);
//function onDeviceReady() {
//Loads Google Map
var mapOptions = {
center: new google.maps.LatLng(0,0),
zoom: 16,
mapTypeId: google.maps.MapTypeId.ROADMAP,
mapTypeControl: false,
streetViewControl: false
};
var map = new google.maps.Map(document.getElementById("map"), mapOptions);
var myPost = TrackLocation.track();
console.log(myPost);
//}
})
Factory
.factory('TrackLocation', function($http, $cordovaGeolocation) {
return {
track: function() {
console.log("Started Tracking");
var lat, long;
var watchOptions = {
timeout : 3000,
enableHighAccuracy: true
};
var watch = $cordovaGeolocation.watchPosition(watchOptions);
watch.then(
null,
function(err) {
console.log(err);
return "lole";
},
function(position) {
lat = position.coords.latitude
long = position.coords.longitude
console.log(lat);
});
return {'lat': lat, 'long':long };
},
stop: function() {
}
};
})
Console Log
Started Tracking
Object {lat: undefined, long: undefined}
103 14.408132700000001
the myPost was return with an undefined value because it was called before the real value was pass on the lat.
Please help.
You should return just watch in your track method or return promise and than in success callback resolve this promise with lat and long values.
I'm trying to implement Google maps in Angular / IonicFramework. I'm using a directive, a service, and a controller. I have a map, marker, and geolocation object in $scope. The map object and the marker object in the view updates from the service however the geolocation object doesn't.
The template/view:
<div class="item item-input item-stacked-label item-icon-right">
<div>
Location
<a ng-click="centerOnMe()">
<i class="icon ion-android-locate" style="font-size:24px"></i>
</a>
</div>
<textarea style="margin-top: 0px; margin-bottom: 0px; height: 45px;" placeholder="Location not found." disabled>{{geoloc.addr}}</textarea>
</div>
<div class="item item-input">
<div class="input-label">Map</div>
</div>
<div class="item item-input" style="height:15em;">
<ion-content scroll="false">
<map on-create="mapCreated(map, geoloc, marker)"></map>
</ion-content>
</div>
The map directive:
angular.module('starter.directives', [])
.directive('map', function(MapService) {
return {
restrict: 'E',
scope: {
onCreate: '&'
},
link: function ($scope, $element, $attr) {
function initialize() {
var mapOptions = {
center: new google.maps.LatLng(43.07493, -89.381388),
zoom: 16,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map($element[0], mapOptions);
var geoloc = {
lat: null, lng: null, str: null, brgy: null,
muni: null, reg: null, addr: null
};
var marker = new google.maps.Marker({
map: map
});
$scope.onCreate(
{
map: map, //link map to map in controller
geoloc: geoloc, //link geoloc to geoloc in controller
marker: marker //link marker to marker in controller
});
// Stop the side bar from dragging when mousedown/tapdown on the map
google.maps.event.addDomListener($element[0], 'mousedown', function (e) {
e.preventDefault();
return false;
});
}
if (document.readyState === "complete") {
initialize();
} else {
google.maps.event.addDomListener(window, 'load', initialize);
}
}
}
});
The map controller:
angular.module('starter.controllers', [])
.controller('MapCtrl', function($scope, $ionicLoading, MapService) {
$scope.mapCreated = function(map, geoloc, marker) {
$scope.map = map; //sets the map from the directive to the $scope
$scope.geoloc = geoloc; //sets the geoloc from the directive to the $scope
$scope.marker = marker; //sets the marker from the directive to the $scope
};
$scope.centerOnMe = function () {
console.log('Centering..');
if (!$scope.map && !$scope.marker && !$scope.geoloc) {
return;
}
$scope.loading = $ionicLoading.show({
template: 'Getting current location...',
noBackdrop: true
});
$scope.geoloc = MapService.getCurrentLocation($ionicLoading, $scope.map, $scope.geoloc, $scope.marker);
// ^^^ This doesn't seem to work. $scope.geoloc doesn't get updated immediately, while $scope.map and $scope.marker gets updated immediately. Has to be invoked twice for $scope.geoloc to be updated.
}
});
The map service:
angular.module('starter.services', [])
.factory('MapService', function() {
return {
getCurrentLocation: function($ionicLoading, map, geoloc, marker) {
navigator.geolocation.getCurrentPosition(function (pos) { //callback if get location succeeds
geoloc.lat = pos.coords.latitude;
geoloc.lng = pos.coords.longitude;
var latlngpos = new google.maps.LatLng(pos.coords.latitude, pos.coords.longitude);
var geocoder = new google.maps.Geocoder();
geocoder.geocode({'latLng': latlngpos}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[0]) {
map.setZoom(16);
marker.setOptions({
position: latlngpos,
map: map
});
geoloc.str = results[0].address_components[0].short_name; //type:route
geoloc.brgy = results[0].address_components[1].short_name; //type:neighborhood
geoloc.muni = results[0].address_components[2].short_name; //type:locatlity
geoloc.reg = results[0].address_components[3].short_name; //type:admnistrative_area_level_1
geoloc.addr = results[0].formatted_address;
} else {
console.log('No results found');
}
} else {
console.log('Geocoder failed due to: ' + status);
}
});
map.setCenter(latlngpos);
$ionicLoading.hide();
}, function (error) { //callback if get location fails
alert('Unable to get location: ' + error.message);
});
return geoloc;
}
}
})
;
I based my implementation here:
http://www.jeffvandalsum.com/integrating-google-maps-api-with-angular/
And I already followed the solutions as suggested here, however the $scope.geoloc object still doesn't update:
Angular directive scope between google maps and a controller
Phonegap not firing GoogleMaps v3 domListener function inside Angularjs directive
Try wrapping
$scope.geoloc = MapService.getCurrentLocation($ionicLoading,$scope.map, $scope.geoloc, $scope.marker);
with $timeout
angular.module('starter.controllers', [])
.controller('MapCtrl', function($scope,$timeout, $ionicLoading, MapService) {
$scope.mapCreated = function(map, geoloc, marker) {
$scope.map = map; //sets the map from the directive to the $scope
$scope.geoloc = geoloc; //sets the geoloc from the directive to the $scope
$scope.marker = marker; //sets the marker from the directive to the $scope
};
$scope.centerOnMe = function () {
console.log('Centering..');
if (!$scope.map && !$scope.marker && !$scope.geoloc) {
return;
}
$scope.loading = $ionicLoading.show({
template: 'Getting current location...',
noBackdrop: true
});
$timeout(function(){
$scope.geoloc = MapService.getCurrentLocation($ionicLoading, $scope.map, $scope.geoloc, $scope.marker);
// ^^^ This doesn't seem to work. $scope.geoloc doesn't get updated immediately, while $scope.map and $scope.marker gets updated immediately. Has to be invoked twice for $scope.geoloc to be updated.
});
}
});
Side Note: This isn't necessarily the best way, but it should trigger your $scope.geoloc to to update correctly.
I would also suggest Gajotres's tutorial.
Hope this was helpful!
I just rewrote my directive, service, and controller, and now it's working. the data now is contained in the service. Then I just injected the service to the directive and the controller.
The map service:
.factory('MapService', function() {
var service = {};
service.map = null;
service.marker = null;
service.geoloc = {
lat: 0.0,
lng: 0.0,
str: "",
brgy: "",
muni: "",
reg: "",
addr: ""
};
service.init = function(map, marker) {
this.map = map;
this.marker = marker;
}
service.getCurrLoc = function($ionicLoading) {
navigator.geolocation.getCurrentPosition(function (pos) { //callback if get location succeeds
service.geoloc.lat = pos.coords.latitude;
service.geoloc.lng = pos.coords.longitude;
var latlngpos = new google.maps.LatLng(pos.coords.latitude, pos.coords.longitude);
var geocoder = new google.maps.Geocoder();
service.marker = new google.maps.Marker({
position: latlngpos,
map: service.map
});
//get location
geocoder.geocode({'latLng': latlngpos}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[0]) {
service.map.setZoom(16);
service.marker.setOptions({
position: latlngpos,
map: service.map
});
service.geoloc.str = results[0].address_components[0].short_name; //type:route
service.geoloc.brgy = results[0].address_components[1].short_name; //type:neighborhood
service.geoloc.muni = results[0].address_components[2].short_name; //type:locatlity
service.geoloc.reg = results[0].address_components[3].short_name; //type:admnistrative_area_leveservice
service.geoloc.addr = results[0].formatted_address;
service.map.setCenter(latlngpos);
$ionicLoading.hide(); //hide loading prompt
} else {
console.log('No results found');
}
} else {
console.log('Geocoder failed due to: ' + status);
}
});
},
function (error) { //callback if get location fails
},
{ enableHighAccuracy: true }); //geolocation options
}
return service;
})
The map directive:
.directive('map', ["MapService", function(MapService) {
return {
restrict: 'E',
scope: {
onCreate: '&'
},
link: function ($scope, $element, $attr) {
function initialize() {
var mapOptions = {
//set to Philippines
center: new google.maps.LatLng(14.6839606, 121.0622039),
zoom: 16,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
MapService.map = new google.maps.Map($element[0], mapOptions);
MapService.marker = new google.maps.Marker({
map: MapService.map
});
$scope.onCreate(
{
map: MapService.map, //link map to map in controller
marker: MapService.marker, //link marker to marker in controller
geoloc: MapService.geoloc //link geoloc to geoloc in controller
}
);
// Stop the side bar from dragging when mousedown/tapdown on the map
google.maps.event.addDomListener($element[0], 'mousedown', function (e) {
e.preventDefault();
return false;
});
}
if (document.readyState === "complete") {
initialize();
} else {
google.maps.event.addDomListener(window, 'load', initialize);
}
}
}
}])
The map controller:
.controller('MapCtrl', ["$scope", "$ionicLoading", "MapService", function($scope, $ionicLoading, MapService) {
$scope.mapCreated = function(map, marker, geoloc) {
$scope.map = map; //sets the map from the directive to the $scope
$scope.marker = marker; //sets the marker from the directive to the $scope
$scope.geoloc = geoloc; //sets the geoloc from the directive to the $scope
console.log('$scope.geoloc in $scope.mapCreated', $scope.geoloc);
$scope.centerOnMe();
};
$scope.centerOnMe = function () {
console.log("Centering");
if (!$scope.geoloc && !$scope.map && !$scope.marker) {
console.log($scope.map);
console.log($scope.marker);
console.log($scope.geoloc);
return;
}
$scope.loading = $ionicLoading.show({
template: 'Getting current location...',
noBackdrop: true
});
MapService.getCurrLoc($ionicLoading);
}
}])