Here Map stacks in Bootstraps Modal - here-api

I have several modal buttons which on click should show pre-saved Map Route in PolyLine.
Below code I used on php Ajax Modal Call. $jsline, $center_lat, $center_lng are php variable which are determined on modal click by ajax query.
<div id="map" style="width:100%;height:450px"></div>
<script>
$(document).on("shown.bs.modal", function () {
function addPolylineToMap(map) {
var lineString = new H.geo.LineString();
'.$jsline.'
map.addObject(new H.map.Polyline(
lineString, { style: { lineWidth: 4 }}
));
}
var platform = new H.service.Platform({
apikey: myhereapi
});
var defaultLayers = platform.createDefaultLayers();
var map = new H.Map(document.getElementById("map"),
defaultLayers.vector.normal.map,{
center: {lat:'.$center_lat.', lng:'.$center_lng.'},
zoom: 5.65,
pixelRatio: window.devicePixelRatio || 1
});
window.addEventListener("resize", () => map.getViewPort().resize());
var behavior = new H.mapevents.Behavior(new H.mapevents.MapEvents(map));
var ui = H.ui.UI.createDefault(map, defaultLayers);
addPolylineToMap(map);
});
</script>
If I remove on("shown.bs.modal") modal window pops up with blank map (white background, no map). When I use on("shown.bs.modal") modal window pops up and work properly on first click. However, second, third, and further clicks will stack maps. I mean in second click there 2 maps appear. In third click 3 maps appear.
Why maps get stacked ? How to resolve this issue ? As far as I can see no one else faced with similar problem before.

I managed to find solution, so I am sharing it if anyone else faces with such issue.
I have added $("#map").empty(); just before new instance of map is loaded as below.
<div id="map" style="width:100%;height:450px"></div>
<script>
$(document).on("shown.bs.modal", function () {
function addPolylineToMap(map) {
var lineString = new H.geo.LineString();
'.$jsline.'
map.addObject(new H.map.Polyline(
lineString, { style: { lineWidth: 4 }}
));
}
$("#map").empty();
var platform = new H.service.Platform({
apikey: myhereapi
});
var defaultLayers = platform.createDefaultLayers();
var map = new H.Map(document.getElementById("map"),
defaultLayers.vector.normal.map,{
center: {lat:'.$center_lat.', lng:'.$center_lng.'},
zoom: 5.65,
pixelRatio: window.devicePixelRatio || 1
});
window.addEventListener("resize", () => map.getViewPort().resize());
var behavior = new H.mapevents.Behavior(new H.mapevents.MapEvents(map));
var ui = H.ui.UI.createDefault(map, defaultLayers);
addPolylineToMap(map);
});
</script>

Related

Know when the dommarkers appear

How to intercept when dommarker appears on the map?
I noticed that if the marker is not visible on the screen, there is not even its html code, I have to change a couple of styles, I need to know when they reappear
I use JavaScript API 3.0
This is a well-hidden feature which is documented here: http://developer.here.com/javascript-apis/documentation/v3/maps/topics_api_nlp/h-map-domicon.html#h-map-domicon
The idea is to add onAttach (and/or onDetach) callbacks to the DOM icon to be notified when a marker comes into the viewport using that icon. Watch out though because the DOM icon you create is always cloned before being put into a marker (because you can use the same DOM icon on multiple markers). The link should already show how it is done, but I'm adding a snippet below.
//Initialization business
var platform = new H.service.Platform({
app_id: 'DemoAppId01082013GAL',
app_code: 'AJKnXv84fjrb0KIHawS0Tg',
useCIT: true
});
var defaultLayers = platform.createDefaultLayers();
var map = new H.Map(document.getElementById('mapp'), defaultLayers.normal.map, {
center: {
lat: 52.3,
lng: 13.8
},
zoom: 10
});
var behavior = new H.mapevents.Behavior(new H.mapevents.MapEvents(map));
//The onAttach function receives the DomElement, the icon object and the
//marker. The element can now be styled...
var onAttach = function(element, icon, marker) {
console.log("marker entering", element, icon, marker);
};
//Create a DomElement to use as marker icon...
var domIconEl = document.createElement("div");
domIconEl.style.width = "32px";
domIconEl.style.height = "32px";
domIconEl.style.marginLeft = "-16px";
domIconEl.style.marginTop = "-16px";
domIconEl.style.borderRadius = "20px";
domIconEl.style.background = "#006";
//Create icon with icon element adding onAttach to the options
var domIcon = new H.map.DomIcon(domIconEl, {
onAttach: onAttach
});
//Creare marker and add to map
var domMarker = new H.map.DomMarker({
lat: 52.3,
lng: 13.8
}, {
icon: domIcon
});
map.addObject(domMarker);

Upgrading dual map program from Google Maps apiV2 to apiV3

I have a Google map API V2 script allowing two maps of different sizes and zoom levels to move together, when one map is panned the other also moves to maintain the same center point. The smaller map has a Xhair in the center that returns to the center after it has been panned, the larger map has multiple markers.
I'm trying to upgrade the code to API V3, but the V3 maps aren't moving each other and the smaller map Xhair isn't functioning. Can someone please tell me what am I missing in the script upgrade from API V2 to API V3?
V2 code:
<script type="text/javascript">
//<![CDATA[
if (GBrowserIsCompatible()) {
function createMarker(point) {
map.addOverlay(new GMarker(point));
}
// ===== Setup The Maps =====
// Display the main map, with some controls and set the initial location
var map = new GMap2(document.getElementById("map"));
map.addControl(new GLargeMapControl());
map.addControl(new GMapTypeControl());
map.setCenter(new GLatLng(54.531283,-125.125537), 12);
// Set up three markers on the main map
createMarker(new GLatLng(54.207882,-125.661621));
createMarker(new GLatLng(49.214790,-124.054399));
createMarker(new GLatLng(49.053632,-122.352859));
// create the crosshair icon, which will indicate where we are on the minimap
// Lets not bother with a shadow
var Icon = new GIcon();
Icon.image = "xhair.png";
Icon.iconSize = new GSize(21, 21);
Icon.shadowSize = new GSize(0,0);
Icon.iconAnchor = new GPoint(11, 11);
Icon.infoWindowAnchor = new GPoint(11, 11);
Icon.infoShadowAnchor = new GPoint(11, 11);
// Create the minimap
var minimap = new GMap2(document.getElementById("minimap"));
minimap.setCenter(new GLatLng(54.531283,-125.125537), 7);
// Add the crosshair marker at the centre of the minimap and keep a reference to it
var xhair = new GMarker(minimap.getCenter(), Icon);
minimap.addOverlay(xhair);
// ====== Handle the Map movements ======
// Variables that log whether we are currently causing the maps to be moved
var map_moving = 0;
var minimap_moving = 0;
// This function handles what happens when the main map moves
// If we arent moving it (i.e. if the user is moving it) move the minimap to match
// and reposition the crosshair back to the centre
function Move(){
minimap_moving = true;
if (map_moving == false) {
minimap.setCenter(map.getCenter());
xhair.setPoint(map.getCenter());
xhair.redraw(true);
}
minimap_moving = false;
}
// This function handles what happens when the mini map moves
// If we arent moving it (i.e. if the user is moving it) move the main map to match
// and reposition the crosshair back to the centre
function MMove(){
map_moving = true;
if (minimap_moving == false) {
map.setCenter(minimap.getCenter());
xhair.setPoint(minimap.getCenter());
xhair.redraw(true);
}
map_moving = false;
}
// Listen for when the user moves either map
GEvent.addListener(map, 'move', Move);
GEvent.addListener(minimap, 'moveend', MMove);
}
// display a warning if the browser was not compatible
else {
alert("Sorry, the Google Maps API is not compatible with this browser");
}
Non-working V3 code:
<script type="text/javascript">
function createMarker(point) {
map.addOverlay(new google.maps.Marker(point));
}
// ===== Setup The Maps =====
// Display the main map, with some controls and set the initial location function initialize() {
var map = new google.maps.Map(
document.getElementById('map'), {
center: new google.maps.LatLng(54.531283,-125.125537),
zoom: 12,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
// Set up three markers on the main map
var marker = new google.maps.Marker({
position: new google.maps.LatLng(54.207882,-125.661621),
map: map
});
var marker = new google.maps.Marker({
position: new google.maps.LatLng(49.214790,-124.054399),
map: map
});
var marker = new google.maps.Marker({
position: new google.maps.LatLng(49.053632,-122.352859),
map: map
});
// create the crosshair icon, which will indicate where we are on the minimap
// Lets not bother with a shadow
var Icon = new google.maps.MarkerImage();
Icon.image = "xhair.png";
Icon.iconSize = new google.maps.Size(21, 21);
Icon.shadowSize = new google.maps.Size(0,0);
Icon.iconAnchor = new google.maps.Point(11, 11);
Icon.infoWindowAnchor = new google.maps.Point(11, 11);
Icon.infoShadowAnchor = new google.maps.Point(11, 11);
// Create the minimap
var minimap = new google.maps.Map(
document.getElementById('minimap'), {
center: new google.maps.LatLng(54.531283,-125.125537),
zoom: 7,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
// Add the crosshair marker at the centre of the minimap and keep a reference to it
var xhair = new google.maps.Marker(minimap.getCenter(), Icon);
minimap.addOverlay(xhair);
// ====== Handle the Map movements ======
// Variables that log whether we are currently causing the maps to be moved
var map_moving = 0;
var minimap_moving = 0;
// This function handles what happens when the main map moves
// If we arent moving it (i.e. if the user is moving it) move the minimap to match
// and reposition the crosshair back to the centre
function Move(){
minimap_moving = true;
if (map_moving == false) {
minimap.setCenter(map.getCenter());
xhair.setPoint(map.getCenter());
xhair.redraw(true);
}
minimap_moving = false;
}
// This function handles what happens when the mini map moves
// If we arent moving it (i.e. if the user is moving it) move the main map to match
// and reposition the crosshair back to the centre
function MMove(){
map_moving = true;
if (minimap_moving == false) {
map.setCenter(minimap.getCenter());
xhair.setPoint(minimap.getCenter());
xhair.redraw(true);
}
map_moving = false;
}
// Listen for when the user moves either map
google.maps.event.addListener(map, 'move', Move);
google.maps.event.addListener(minimap, 'moveend', MMove);
// google.maps.event.addDomListener(window, 'load', initialize);
google.maps.event.addDomListener(window, 'load', initialize);
The upgrade guide seems to have little information on Events, some obsolete events don't seem to be listed in the obsolete code. The V2 events: "move" and "moveend" are apparently not supported in V3, however there are similar (but not the same) V3 events; dragstart, drag, dragend, and center_changed. Since the drag events aren't compatable with additional selection buttons I'm using: I went with center_changed which works like a charm for my application.
I explored a few options for the center cross hair, but they seemed to have dead spots or jumped around when the maps were panned, so I eliminated the javascript solutions and went with a simple solution from Drew Noakes.
This is what I came up with to fix the non-working V3 code, might help someone out there.
V3 code:
<script type="text/javascript">
// ===== Setup The Maps =====
// Display the main map and set the initial location
var map = new google.maps.Map(
document.getElementById('map'), {
center: new google.maps.LatLng(54.531283,-125.125537),
zoom: 12,
zoomControl: false,
scaleControl: true,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
// Set up the three markers on the main map
var marker = new google.maps.Marker({
position: new google.maps.LatLng(54.207882,-125.661621),
map: map
});
var marker = new google.maps.Marker({
position: new google.maps.LatLng(49.214790,-124.054399),
map: map
});
var marker = new google.maps.Marker({
position: new google.maps.LatLng(49.053632,-122.352859),
map: map
});
// Create the minimap
var minimap = new google.maps.Map(
document.getElementById('minimap'), {
center: new google.maps.LatLng(54.531283,-125.125537),
zoom: 7,
zoomControl: false,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
// Add the crosshair marker at the centre of the minimap using html and CSS
// ====== Handle the Map movements ======
// Variables that log whether we are currently causing the maps to be moved
var map_moving = 0;
var minimap_moving = 0;
// This function handles what happens when the main map moves
// If we arent moving it (i.e. if the user is moving it) move the minimap to match
google.maps.event.addListener(map, 'center_changed', function(){
minimap_moving = true;
if (map_moving == false) {
minimap.setCenter(map.getCenter());
}
minimap_moving = false;
})
// This function handles what happens when the mini map moves
// If we arent moving it (i.e. if the user is moving it) move the main map to match
google.maps.event.addListener(minimap, 'center_changed', function(){
map_moving = true;
if (minimap_moving == false) {
map.setCenter(minimap.getCenter());
}
map_moving = false;
})
// google.maps.event.addDomListener(window, 'load', initialize);
google.maps.event.addDomListener(window, 'load', initialize);
</script>
//The HTML:
<div id="map" style="width:627px; height: 627px"></div>
<div id="container">
<div id="minimap" style="width:370px; height:370px;"></div>
<div id="xhair"><img src="../images/xhair.png" width="20" height="20" /></div>
</div>
//The CSS:
#container { position:relative; }
#map { height:100%; width:100%; }
#xhair {
position:absolute;
left:47%;
top:47%;
}

How to add a marker on a groundoverlay by a click?

I developed a map application using gmap2. I used a groundoverlay (a temperature map) to help users to determine the location of interest and click to select. After gmap2 being replaced by gmap3, it stops working. The bigger problem is that I could not find a way to add markers on the groundoverlay by clicking in gmap3. Someone raised a similar question, but no answer has been available. I hope that such a function is not lost in gmap3. Your help is appreciated.
enter code here
<script>
var map;
var mapCenter = new google.maps.LatLng(54.508742, -125.120850);
var pngBounds = new google.maps.LatLngBounds(new google.maps.LatLng(48.3367, -139.0402),
new google.maps.LatLng(59.99008, -114.1095));
function initialize() {
var mapProp = { center: mapCenter, zoom: 5, mapTypeId: google.maps.MapTypeId.ROADMAP };
map = new google.maps.Map(document.getElementById("googleMap"), mapProp);
var groundoverlay = new google.maps.GroundOverlay(
"http://www.genetics.forestry.ubc.ca/cfcg/ClimateBC40/overlays/climate/MAT_1961_1990.png", pngBounds);
groundoverlay.setMap(map);
google.maps.event.addListener(map, 'click', function (event) { placeMarker(event.latLng); });
}
function placeMarker(location) {
var marker = new google.maps.Marker({ position: location, map: map, draggable: true });
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
In v3 you have to make the groundOverlay non-clickable
var groundoverlay = new google.maps.GroundOverlay(
"http://www.genetics.forestry.ubc.ca/cfcg/ClimateBC40/overlays/climate/MAT_1961_1990.png", pngBounds, **{clickable:false}**);
use below code as simple as that..
let overlayGeoMapImg = new google.maps.GroundOverlay(
'../assets/GNDVI.png',
imageBounds);
overlayGeoMapImg.setMap(map);
google.maps.event.addListener(overlayGeoMapImg, 'click', (event: any) => {
this.ngZone.run(() => {
marker = new google.maps.Marker({
position: event.latLng,
map: map,
title: 'Hello World!'
});
});
});

Google Maps API with backbone, how to bind an event

I've seen several other posts about this, but the answers from those responses don't work for me.
The other responses:
How do I bind a google maps geocoder.geocode() callback function
Backbone.js with Google Maps - problems with this and listeners
My code:
var ns = namespace('camelcase.geomanager.map');
ns.Site = Backbone.Model.extend({
url: '/site'
});
ns.Sites = Backbone.Collection.extend({
model: ns.Site
});
ns.MapView = Backbone.View.extend({
initialize: function() {
this.markers = new Array();
// Create the Google Map
var mapOptions = {
center: new google.maps.LatLng(-34.397, 150.644),
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
this.googleMap = new google.maps.Map(this.$(".mapCanvas")[0], mapOptions);
// Register events
this.collection.on('add', this.addSite, this);
this.collection.on('remove', this.removeSite, this);
},
addSite: function(model) {
// Get model attributes
var elementId = model.get('elementId');
var latitude = model.get('latitude');
var longitude = model.get('longitude');
var id = model.get('id');
var notes = model.get('notes');
var title = ""+id;
// Create icon and marker
var icon = '/resources/img/elements/' + elementId + '_marker.png';
var latLng = new google.maps.LatLng(latitude, longitude);
var marker = new google.maps.Marker({
position: latLng,
title: title,
map: this.googleMap,
icon: icon
});
// Load info window
var siteBubbleTemplate = _.template($('#siteBubbleTemplate').html());
var siteContent = $(siteBubbleTemplate({
siteId: id,
siteNotes: notes
}))[0];
var infoWindow = new google.maps.InfoWindow({
content: siteContent
});
// Show info window when clicking on marker
_.bindAll(this, this.openSite);
google.maps.event.addListener(marker, 'click', this.openSite(id));
this.markers.push({
id: id,
marker: marker,
infoWindow: infoWindow
});
},
openSite: function(id) {
var marker;
for (var c=0; c<this.markers.length; c++) {
marker = this.markers[c];
// Open the appropriate marker info window
if (marker.id == id) {
marker.infoWindow.open(googleMap, marker.marker);
}
// Close the rest
else {
marker.infoWindow.close();
}
}
}
});
The offending line:
google.maps.event.addListener(marker, 'click', this.openSite(id));
The error being reported in firebug:
TypeError: func is undefined
underscore.js (line 482)
I suspect this.marker is the problem, since you should be able to just refer to it by name.
google.maps.event.addListener(marker, 'click', this.openSite(id));
Looks like it was a scoping issue. I solved my problem with the following code:
// Show info window when clicking on marker
_.bindAll(this);
var _self = this;
var doSomething = function(event) {
_self.openSite({
event: event
});
};
google.maps.event.addListener(marker, 'click', doSomething);
I'll give the answer to whoever can best explain why this works.
In a model/collection event handler, Backbone sets 'this' to the model/collection which raised the event. If you call _.bindAll(this) in your view's initialize(), 'this' will be set to the view in your event handlers. Check out this jsfiddle: http://jsfiddle.net/9cvVv/339/ and see what happens when you uncomment _.bindAll(this);
var MyView = Backbone.View.extend({
initialize: function() {
// TODO: uncomment this line
// _.bindAll(this);
this.collection.bind('myEvent', this.onDoSomething);
},
updateCollection: function() {
this.collection.doSomething();
},
onDoSomething: function() {
if (this.models && typeof this.models.length === 'number') {
alert('"this" is a collection.');
}
else if (this.collection) {
alert('"this" is the view.');
}
else {
alert('"this" is something else.');
}
}
});

Getting the LatLng from placed marker for browser fields

Tried the following scripts but the last section is not working. Help please.
// script type="text/javascript"
var myOptions = {
zoom: 7,
center: new google.maps.LatLng(-36.624345125527526,144.96459973437504),
mapTypeId: google.maps.MapTypeId.TERRAIN,
streetViewControl: false,
draggableCursor: 'crosshair',
draggingCursor: 'pointer'
};
var map = new google.maps.Map(document.getElementById('map_canvas'),
myOptions);
google.maps.event.addListener(map, 'click', function(e) {
placeMarker(e.latLng, map);
});
map.panTo(position);
// not working
google.maps.event.addListener(marker, 'dragend', function() {
var point = marker.getPosition();
document.getElementById("latitude").getElementsByTagName("input")[0].value = point.lat();
document.getElementById("longitude").getElementsByTagName("input")[0].value = point.lng();
});
// end of script
Tried using the following but nothing happen after the marker is drag. Seems like the listener is not listening to the 'dragend' event of the marker. Any clue? Other option to get the latLng after dragging marker on map?
// JS code
google.maps.event.addListener(marker, 'dragend', function(e) {
var point = e.latLng;
alert(marker.e.latLng);
})
// end code
The input elements part is not a choice as the scripts sit in an embedded placeholder of a web based application. So can't change that part.
You should be using the MouseEvent object passed by the dragend event for the marker. Like this:
google.maps.event.addListener(marker, 'dragend', function(e) {
var point = e.latLng;
document.getElementById("latitude").getElementsByTagName("input")[0].value = point.lat();
document.getElementById("longitude").getElementsByTagName("input")[0].value = point.lng();
});
I also am not sure why you're not just naming your input elements and accessing them directly...something like this:
document.getElementById("latitude_input").value = point.lat();
document.getElementById("longitude_input").value = point.lng();

Resources