calling a function in angular controller from google api present in view - javascript

i am using google places details api. So in my src attribute I put google api which has a callback named initMap
Here is the code
<div class="tab-pane active" id="timeline">
<p class="lead">Location</p>
<hr>
<div class="row">
<div class="col-md-1"></div>
<div class="col-md-8">
<h2>
<span>location <b style="color:black;"> kolkata</b></span></h2>
<p></p>
<div id="map" style="width:100%;height:400px;"></div>
<script src="https://maps.googleapis.com/maps/api/js?key=API_KEY&libraries=places&callback=initMap"></script>
<p></p>
</div>
</div>
</div>
In same html I have written initMap function
<script>
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 22.652687, lng: 88.376882},
zoom: 15
});
var infowindow = new google.maps.InfoWindow();
var service = new google.maps.places.PlacesService(map);
service.getDetails({
placeId: 'ChIJvYbRT7Gd-DkR6QZQfJP9ZJg'
}, function(place, status) {
debugger
if (status === google.maps.places.PlacesServiceStatus.OK) {
var marker = new google.maps.Marker({
map: map,
position: place.geometry.location
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent('<div><strong>' + place.name + '</strong><br>' +
'Place ID: ' + place.place_id + '<br>' +
place.formatted_address + '</div>');
infowindow.open(map, this);
});
}
});
}
</script>
This works perfectly as long as this function is present inside script tag.
How do I call initMap inside controller?

You can't call it that way but instead you will load the script using javascript inside your controller when your app is loaded using document.createElement('script') then hook up a onload event listener then append it inside head head tag.
most likely:
var script = document.createElement('script');
script.src = 'google api script';
script.onload = function () {
// your onload function
$scope.onload();
$scope.$digest();
};
document.querySelector('head').appendChild(script);
this way you have control over what ng stuff you want to do everytime it loads. hope that helps

When inside your HTML page, you create a function, the function will be automatically assigned to the window object, because that's the default scope of the scripts included in the page.
So from your controller, you should be able to simply call the function just using: window.initMap();

Related

pass lat lng to javascript laravel

i have this button and onclick i want to pass lat lng to initialize function for google map:
<button class="btn btn-block btn-primary" onclick="initialize()" id='latlng' lat="{{$data['clients_address']['lat']}}" lng="{{$data['clients_address']['lng']}}">
Map Location
</button>
i tried passing with this event but its not working and if with jquery then how can i pass to javascript function
$('#latlng').click(function(e){
var lng = $(this).attr('lng');
alert(lng,lat);
});
<script>
function initialize() {
//console.log(this.getAttribute('lat'));
var latlng = new google.maps.LatLng(28.535516,77.391026);
var map = new google.maps.Map(document.getElementById('map'), {
center: latlng,
zoom: 13
});
var marker = new google.maps.Marker({
map: map,
position: latlng,
draggable: false,
anchorPoint: new google.maps.Point(0, -29)
});
var infowindow = new google.maps.InfoWindow();
google.maps.event.addListener(marker, 'click', function() {
var iwContent = '<div id="iw_container">' +
'<div class="iw_title"><b>Location</b> : Noida</div></div>';
// including content to the infowindow
infowindow.setContent(iwContent);
// opening the infowindow in the current map and at the current marker location
infowindow.open(map, marker);
});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
In your example, you first used a .click to an ID selector. If you really only have one button that calls initialize() on the page you can pass PHP variables directly to Javascript:
<script>
let lat = <?php echo json_encode($data['clients_address']['lng']); ?>;
let lng = <?php echo json_encode($data['clients_address']['lng']); ?>;
function initialize() {
...
}
</script>
If you have multiple initialize() triggers, you can use #Mahmoud answer or pass the values as function parameters.
<button class="btn btn-block btn-primary" onclick="initialize({{$data['clients_address']['lat']}}, {{$data['clients_address']['lng']}})" id="latlng">
Map Location
</button>
function initialize(lat, long) {
...
}
Personally I tend to use this + element attributes when I need to reference a standard attribute (ex: value, class) or the value is referenced in more than one place (ex: not only in initialize function). Also, consider using jQuery data method if you intend to use attributes.
Att,
First you need to pass the clicked element to the initialize like so
<button class="btn btn-block btn-primary" onclick="initialize(this)" id='latlng' lat="{{$data['clients_address']['lat']}}" lng="{{$data['clients_address']['lng']}}">
Map Location
</button>
then in your initialize function you will get the lat and lng
function initialize(element) {
var lat = $(element).attr('lat');
var lng = $(element).attr('lng');
.....
}

Hide a marker in Google Maps API Javascript

I am loading a bunch of markers based on a dataset that I am reading from Mongodb in my ejs file. I just loop through the markers to add them to the map and then a "click" eventlistener to display some comment for each marker in the infowindow:
var infowindow = new google.maps.InfoWindow();
var marker, i;
<%for (i = 0; i < <%=comments.length%>; i++) {%>
var LatLng = {lat: <%=comments[i].lat, lng: <%=comments[i].lng%>};
var marker = new google.maps.Marker({
position: LatLng,
map:map,
title: 'Click to see comment details',
id:'<%=comments[i]._id%>'
});
marker.addListener('click', (function(marker, i) {
return function() {
var contentString = `
<div class="comment-item">
<div id="bodyContent">
<p class="lead mt-2"><%=comments[i].textComment%></p>
</div>
</div>
<div>
<form style="display: inline" method="POST" action="/admin/comments/<%=comments[i]._id%>" class="approve-comment-form">
<input type="submit" value="Approve Comment" class="btn btn-success"/>
</form>
</div>
`
infowindow.setContent(contentString);
infowindow.open(map, marker);
}
})(marker, i));
<%}%>
What I am trying to do is to submit the form (approve the comment) using ajax code below. This basically, updates a field for that comment in my Mongodb document.
$(document).on('submit','.approve-comment-form', function(event){
event.preventDefault();
var editCommentData = $(this).serialize();
var editCommentAction = $(this).attr('action');
var $originalCommentItem = $(this).parent('.comment-item');
$.ajax({
url: editCommentAction,
data: editCommentData,
type: 'PUT',
originalItem: $originalCommentItem,
success: function(data) {
console.log(data)
}
});
})
So, the form submission works well and if I refresh the page, that marker will not be displayed on the map (Because the "ajax put" method toggles a switch from on to off for that marker and on page reload it won't be displayed), but the problem is that I want the marker to hide also with the form submit (Without the page refresh) so that I know I have already approved the comment inside it.

Repeatition of map div in ng repeat

I have a card where it is repeated multiple times in a page, In the card I have a google map which shows the location of a particular point.
I am getting the google side response as
Error
at new nc (https://maps.googleapis.com/maps/api/js?key=AIzaSyCEHWgPqgJiWcySMQPZZ7W7Cjpugl928Fw&callback=renderMap:47:499)
at Object._.oc (https://maps.googleapis.com/maps/api/js?key=AIzaSyCEHWgPqgJiWcySMQPZZ7W7Cjpugl928Fw&callback=renderMap:48:96)
at ah (https://maps.googleapis.com/maps/api/js?key=AIzaSyCEHWgPqgJiWcySMQPZZ7W7Cjpugl928Fw&callback=renderMap:98:420)
at https://maps.googleapis.com/maps/api/js?key=AIzaSyCEHWgPqgJiWcySMQPZZ7W7Cjpugl928Fw&callback=renderMap:137:53
at Object.google.maps.Load (https://maps.googleapis.com/maps/api/js?key=AIzaSyCEHWgPqgJiWcySMQPZZ7W7Cjpugl928Fw&callback=renderMap:21:5)
at https://maps.googleapis.com/maps/api/js?key=AIzaSyCEHWgPqgJiWcySMQPZZ7W7Cjpugl928Fw&callback=renderMap:136:20
at https://maps.googleapis.com/maps/api/js?key=AIzaSyCEHWgPqgJiWcySMQPZZ7W7Cjpugl928Fw&callback=renderMap:137:68
Html code is as follows
<div class="body" ng-repeat="hospital in hospitals">
<div class="list card">
<div>
<div id="map{{$index}}" style="height:200px;width:100%;" class="renderMap(hospital)"></div>
<script async defer src="https://maps.googleapis.com/maps/api/js?key=myKey&callback=renderMap">
</script>
</div>
</div>
</div>
In controller, it is as follows
$scope.renderMap = renderMap;
function renderMap(hospital){
$scope.details_for_map = hospital;
console.log($scope.details_for_map);
initMap();
}
function initMap() {
var latlng = new google.maps.LatLng( $scope.details_for_map.geometry.location.lat, $scope.details_for_map.geometry.location.lng);
var map = new google.maps.Map(document.getElementById('map'+$scope.details_for_map.index), {
zoom: 4,
center: latlng
});
var marker = new google.maps.Marker({
position: latlng,
map: map,
title: 'Hello World!'
});
}
As I am new to ionic and angular js I am not able to figure out what I am doing incorrectly. Please let me know what I can do about it.

context is not defined JavaScript

So referring to the original problem I have here Google Maps Javascript V3 Uncaught TypeError: Cannot read property 'offsetWidth' of null and after doing a lot of googling, I have found a solution which I thought would be workable which is this How to append multiple Google Maps areas to divs using Handlebars.
However, I have implemented mine in the following way
var EmployeeView = function(employee){
this.render = function(){
$('body').append(this.el);
// inside the new div, put the Handlebars template, with the data from the employee
this.el.html(EmployeeView.template(employee)).ready( function() {
var mapOptions = {
center: new google.maps.LatLng(-34.397, 150.644),
zoom: 8
};
var map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
});
return this;
};
this.initialize = function(){
this.el=$("</div>");
window.localStorage.removeItem('paramId');
console.log('removed');
window.localStorage.setItem('paramId',employee);
console.log('added ' + employee.id);
};
this.initialize();
}
EmployeeView.template = Handlebars.compile($("#employee-tpl").html());
Not sure if thats the right way of 'referring' to that solution but now, whenever I run the page, the following error is thrown Uncaught ReferenceError: context is not defined
Anyone got any ideas? and to add, my html is as follows
<body>
<script id="employee-tpl" type="text/x-handlebars-template">
<div class='details'>
<img class='employee-image' src='img/{{firstName}}_{{lastName}}.jpg' />
<ul>
<li>See on map</li>
<li>Share with friends</li>
<li><div id="map-canvas"/></li>
</ul>
<script src="lib/iscroll.js"></script>
<script src="lib/handlebars.js"></script>
<script src="lib/jquery-1.8.2.min.js"></script>
<script src="js/storage/cafe-memory-store.js"></script>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?APIKEY&sensor=true"></script>
<script src="js/MapView.js"></script>
<script src="js/EmployeeView.js"></script>
<script src="js/HomeView.js"></script>
<script src="js/main.js"></script>
</body>
In this line:
$("employee-tpl").append(HTMLtemplate(context))
You are passing an undefined function and one undefined variable (context).
context should contain he id parameter you defined in your HandlebarJS template to be replaced
See on map
HTMLTemplate in your case is EmployeeView.template which holds the HandlebarJS compiled template: it is a function that receives as arguments the context variable ( or maybe the employee variable?)
If I got it right your code should be:
var EmployeeView = function(employee){
this.render = function(){
$('body').append(this.el);
// inside the new div, put the Handlebars template, with the data from the employee
this.el.html(EmployeeView.template(employee))).ready( function() {
var mapOptions = {
center: new google.maps.LatLng(-34.397, 150.644),
zoom: 8
};
var map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
});
return this;
};
this.initialize = function(){
this.el=.$("</div>");
window.localStorage.removeItem('paramId');
console.log('removed');
window.localStorage.setItem('paramId',employee);
console.log('added ' + employee.id);
};
this.initialize();
}
EmployeeView.template = Handlebars.compile($("#employee-tpl").html());
I think you have to pass employee to the template because I saw first_name and last_name in the template.

Windows Store App - WinJS: 0x800a1391 - JavaScript runtime error: 'Windows' is undefined

I'm trying to load a Google map into Windows Store Application. However, having a problem with a native Windows RT function: Windows.UI.Popups.MessageDialog. I'm guessing that the Windows namespace is out of scope, but I can't figure out now to get this function into a scope that will make the Windows namespace accessible. Any help is appreciated.
EDIT: the more I think about this, the more I think it has something to do with the fact that I am loading map.html as the source for an iFrame. So the context of map.html is an iFrame, not a Windows Store App page. I guess the Windows namespace is not available from within an iFrame?
From home.html:
<iframe id="getLocationFrame" src="ms-appx-web:///pages/map/map.html" style="width:600px; height:600px;"></iframe>
Exception:
SCRIPT5009: Unhandled exception at line 50, column 17 in ms-appx-web://76ad865e-25cf-485c-bc77-e18186bfd7ee/pages/map/map.js
0x800a1391 - JavaScript runtime error: 'Windows' is undefined
File: map.js, Line: 50, Column: 17
map.html:
<!DOCTYPE html>
<html>
<head>
<title></title>
<script type="text/javascript" src="//Microsoft.WinJS.1.0/js/base.js"></script>
<script type="text/javascript" src="//Microsoft.WinJS.1.0/js/ui.js"></script>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js? sensor=false"></script>
<script type="text/javascript" src="map.js"></script>
<link href="/pages/map/css/map.css" rel="stylesheet" />
<link href="//Microsoft.WinJS.1.0/css/ui-light.css" rel="stylesheet" />
</head>
<body>
<p>Click to get your location.</p>
<button id="getLocation">Get Location</button><br/>
<div id="mapcontainer"></div><br />
<small>
<a id="anchorLargerMap" href="" style="color:#0000FF;text-align:left" target="_blank">View Larger Map</a>
</small>
</body>
</html>
map.js:
(function () {
"use strict";
WinJS.UI.Pages.define("/pages/map/map.html", {
// This function is called whenever a user navigates to this page. It
// populates the page elements with the app's data.
ready: function (element, options) {
//Button "getLocation" event handler
function getLocationClickHandler(eventInfo) {
var myOptions = {
zoom: 13,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var mapcontainer = document.getElementById("mapcontainer");
var map = new google.maps.Map(mapcontainer, myOptions);
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(locationSuccess, locationFail);
}
}
var namespacePublicMembers = {
locationSucessFunction: locationSuccess,
locationFailFunction: locationFail,
getLocationClickEventHandler: getLocationClickHandler
};
WinJS.Namespace.define("mapPage", namespacePublicMembers);
var getLocationButton = document.getElementById("getLocation");
getLocationButton.addEventListener("click", getLocationClickHandler, false);
function locationSuccess(position) {
var initialLocation = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
map.setCenter(initialLocation);
var marker = new google.maps.Marker({
position: initialLocation,
map: map,
title: "You are here."
});
var latitude = position.coords.latitude;
var longitude = position.coords.longitude;
var url = "http://maps.google.com/maps?q=" + latitude + "," + longitude + "&zoom=13&markers=" + latitude + "," + longitude;
$("#anchorLargerMap").attr('href', url);
}
function locationFail() {
var md = new Windows.UI.Popups.MessageDialog("Could not find you!", "").showAsync; -- ********* THIS LINE THROWS EXCEPTION *********
}
}
});
})();
Code that is executed in the web compartment - your URL says that's where this code is - cannot access WinRT components. You'll need to use postMessage etc to communicate between the two security contexts.
from Map.js:
function locationFail() {
//Can't do this due the the iFrame container
//var md = new Windows.UI.Popups.MessageDialog("Could not find you!", "").showAsync;
window.parent.postMessage("Could not find you!", "*");
}
from Home.js:
(function () {
"use strict";
WinJS.UI.Pages.define("/pages/home/home.html", {
// This function is called whenever a user navigates to this page. It
// populates the page elements with the app's data.
ready: function (element, options) {
window.addEventListener("message", messageReceived, false);
function messageReceived(e) {
if (e.origin === "ms-appx-web://76ad865e-25cf-485c-bc77-e18186bfd7ee") {
var md = new Windows.UI.Popups.MessageDialog(e.data, "");
md.showAsync();
}
};
}
});
})();
I got the solution from this blog: http://css.dzone.com/articles/use-winjs-post-message-iframe

Categories