gmappanel move to the marker coordinate - EXTJS 4 - javascript

function addDoctorLocation(options)
{
var gm = Ext.getCmp('mygooglemap');
var mpoint = new google.maps.LatLng(options.lat,options.lng);
var marker = gm.addMarker(mpoint,options.marker,false,false, options.listeners);
// move the map to the mark and adjust the zoom level at here
}
tree.on('checkchange', function(node){
var data = node.data;
if (data.checked == true){
lati = 5.391788482666016;
longi = 100.29693603515625;
var options = {
lat:lati,
lng:longi,
marker: {title:"Hello World!"},
listeners: {
click: function(e){
}
}
}
addDoctorLocation(options);
}
})
Question
how to move the map to marker there and adjust the zoom level?

gm.setCenter(mpoint);
gm.setZoom(8);
See the methods section of google.maps.Map class here: https://developers.google.com/maps/documentation/javascript/reference?hl=en#Map

Related

arcgis-JS polyline path to follow a div on DRAG

I have this almost working; but instead of it following the kendo modal when dragged, it's following the mouse pointer at all times...
So, currently it's following the mouse pointer and so is the modal; but this is horrible for usability so would just like to stay with and follow the modal on the standard click and drag.
attempt A.) Below is the JavaScript, here is the live demo CodePen. The line should always be with the modal for point B, which it's doing; but the modal should only be movable on drag.
require([
"esri/Map",
"esri/views/MapView",
"esri/Graphic",
"esri/layers/GraphicsLayer",
"esri/geometry/support/webMercatorUtils",
"dojo/dom",
],
function init (Map, MapView, Graphic, GraphicsLayer, webMercatorUtils, dom) {
var map = new Map({
basemap: "topo-vector"
});
var view = new MapView({
container: "viewDiv",
map: map,
center: [-80.96135253906438, 35.9411934679851],
zoom: 3
});
var graphicsLayer = new GraphicsLayer();
map.add(graphicsLayer);
var simpleLineSymbol = {
type: "simple-line",
color: [13,121,190, .9],
style: "short-dash",
width: 3
};
var coordinatesAx;
var coordinatesAy;
var coordinatesBx ;
var coordinatesBy;
var moveAlong = false;
var windowElem;
view.when(function(){
view.on("pointer-move", showCoordinates);
});
// NEW: Stop/start moving the modal along with the pointer by map click
view.when(function(){
view.on("click", function () { moveAlong = !moveAlong;});
});
coordinatesAx = -80.96135253906438;
coordinatesAy = 35.9411934679851;
document.getElementById("modal").onclick = function fun() {
windowElem = document.querySelector('.k-window');
moveAlong = true;
// Bind Kendo dialog dragstart to movement
$("#dialog").data('kendoWindow').bind("dragstart", function (ev) {
//graphicsLayer.removeAll();
moveAlong = true;
showCoordinates(ev);
})
}
function showCoordinates(evt) {
var point = view.toMap({x: evt.x, y: evt.y});
var mp = webMercatorUtils.webMercatorToGeographic(point);
dom.byId("info").innerHTML = mp.x.toFixed(3) + ", " + mp.y.toFixed(3);
coordinatesBx = mp.x.toFixed(3);
coordinatesBy = mp.y.toFixed(3);
var polyline = {
type: "polyline",
paths: [
[coordinatesAx, coordinatesAy],
[coordinatesBx, coordinatesBy]
]
};
var polylineGraphic = new Graphic({
geometry: polyline,
symbol: simpleLineSymbol
})
if (moveAlong) {
if (graphicsLayer.graphics.items.length < 0) {
graphicsLayer.add(polylineGraphic)
} else {
// Recreate the line and reposition the modal
graphicsLayer.removeAll();
graphicsLayer.add(polylineGraphic)
windowElem.style.top = evt.y + 0 + "px";
windowElem.style.left = evt.x + 0 + "px";
}
}
}
});
Attempt B.) Update: I have tried going with this logic I found; although I believe it's arcgis 3.3.. and still can't get it to integrate into my CodePen prototype. Anyways I think this is the logic; just can't seem to get it right.
$profileWindow = $("#" + elem).parents(".outter-div-wrapper");
profileWindowOffset = $profileWindow.offset();
profileWindowWidth = $profileWindow.outerWidth();
profileWindowHeight = $profileWindow.outerHeight();
screenPointTopLeft = new Point(profileWindowOffset.left, profileWindowOffset.top, app.ui.mapview.map.spatialReference);
screenPointTopRight = new Point(profileWindowOffset.left + profileWindowWidth, profileWindowOffset.top, app.ui.mapview.map.spatialReference);
screenPointBottomLeft = new Point(profileWindowOffset.left, profileWindowOffset.top + profileWindowHeight, app.ui.mapview.map.spatialReference);
screenPointBottomRight = new Point(profileWindowOffset.left + profileWindowWidth, profileWindowOffset.top + profileWindowHeight, app.ui.mapview.map.spatialReference);
arrayOfCorners.push(screenPointTopLeft);
arrayOfCorners.push(screenPointTopRight);
arrayOfCorners.push(screenPointBottomLeft);
arrayOfCorners.push(screenPointBottomRight);
//convert to screenpoint
graphicsScreenPoint = esri.geometry.toScreenPoint(app.ui.mapview.map.extent, app.ui.mapview.map.width, app.ui.mapview.map.height, self.mapPoint_);
//find closest Point
profileWindowScreenPoint = this.findClosest(arrayOfCorners, graphicsScreenPoint);
//convert from screen point to map point
profileWindowClosestMapPoint = app.ui.mapview.map.toMap(profileWindowScreenPoint);
mapProfileWindowPoint.push(profileWindowClosestMapPoint.x);
mapProfileWindowPoint.push(profileWindowClosestMapPoint.y);
And here is the CodePen with the above attempt added.
Try replacing the JS in your codepen with this code. Needs a bit of work but I think it basically does what you want.
What I changed was to hook into dragstart and dragend of the modal, and use a mouse motion event handler on the document when dragging the modal. I used the document because the events wouldn't get through the dialog to the view behind it.
require([
"esri/Map",
"esri/views/MapView",
"esri/Graphic",
"esri/layers/GraphicsLayer",
"esri/geometry/support/webMercatorUtils",
"dojo/dom",
],
function init(Map, MapView, Graphic, GraphicsLayer, webMercatorUtils, dom) {
var map = new Map({
basemap: "topo-vector"
});
var view = new MapView({
container: "viewDiv",
map: map,
center: [-80.96135253906438, 35.9411934679851],
zoom: 3
});
var graphicsLayer = new GraphicsLayer();
map.add(graphicsLayer);
var simpleLineSymbol = {
type: "simple-line",
color: [13, 121, 190, .9],
style: "short-dash",
width: 3
};
// These were const arrays (??)
var coordinatesAx;
var coordinatesAy;
var coordinatesBx;
var coordinatesBy;
// Chane to true after the dialog is open and when modal starts dragging
var moveAlong = false;
var windowElem;
// view.when(function () {
// view.on("pointer-move", showCoordinates);
// });
// NEW: Stop/start moving the modal along with the pointer by map click
// view.when(function(){
// view.on("click", function () { moveAlong = !moveAlong;});
// });
coordinatesAx = -80.96135253906438;
coordinatesAy = 35.9411934679851;
document.getElementById("modal").onclick = function fun() {
windowElem = document.querySelector('.k-window');
// moveAlong = true;
// Bind Kendo dialog dragstart to movement
$("#dialog").data('kendoWindow').bind("dragstart", function (ev) {
//graphicsLayer.removeAll();
moveAlong = true;
console.log("Dragging");
showCoordinates(ev);
document.addEventListener("mousemove", showCoordinates);
}).bind("dragend", function (ev) {
moveAlong = false;
document.removeEventListener("mousemove", showCoordinates);
console.log("end Dragging");
}).bind("close", function (ev) {
console.log("Close. TODO clear line");
})
}
function showCoordinates(evt) {
var point = view.toMap({ x: evt.x, y: evt.y });
var mp = webMercatorUtils.webMercatorToGeographic(point);
dom.byId("info").innerHTML = mp.x.toFixed(3) + ", " + mp.y.toFixed(3);
coordinatesBx = mp.x.toFixed(3);
coordinatesBy = mp.y.toFixed(3);
var polyline = {
type: "polyline",
paths: [
[coordinatesAx, coordinatesAy],
[coordinatesBx, coordinatesBy]
]
};
var polylineGraphic = new Graphic({
geometry: polyline,
symbol: simpleLineSymbol
})
if (moveAlong) {
if (graphicsLayer.graphics.items.length < 0) {
graphicsLayer.add(polylineGraphic)
} else {
// Recreate the line and reposition the modal
graphicsLayer.removeAll();
graphicsLayer.add(polylineGraphic)
}
}
}
});

How can I add a custom HTML map marker to a Nokia HERE map?

From what I'm reading of the documentation on Nokia maps I can add custom marker using a vector based drawing API:
http://developer.nokia.com/Community/Wiki/HERE_Maps_API_-_How_to_create_custom_graphics_marker
You can create custom graphic markers but only based on a sprite:
http://heremaps.github.io/examples/examples.html#sprite-markers
Or you can add their own markers:
http://developer.nokia.com/Community/Wiki/HERE_Maps_API_-_How_to_add_map_markers
But is there any way to provide an HTML snippet to position on the map like a map marker? That is how other map libraries work so I can completely control the map marker in HTML/CSS. I already have map markers I would like to use that are styled in HTML/CSS and would not like to duplicate that styling in custom JS.
If you are intent on using styled, injected HTML, it would be possible to create a series of custom components (one for each marker) and attach them to the map. This would inject a block level element for each component which you could style as you see fit.
This is not entirely dissimilar to the simple GroundOverlay component I used to use before the ImgTileProvider class was exposed in the API - it injects a <IMG> element and resizes on zoomLevel (which you will probably need to remove) , but still effectively attaches a piece of HTML to a specific anchor point on the map.
For most simple applications I would usually use Markers (with or without my own iconography) or Infobubbles though. These lead to a more responsive and standard UI and don't clutter the map.
function extend(B, A) {
function I() {}
I.prototype = A.prototype;
B.prototype = new I();
B.prototype.constructor = B;
}
function GroundOverlay(url, boundingBox) {
nokia.maps.map.component.Component.call(this);
this.init(url, boundingBox);
}
extend(GroundOverlay,
nokia.maps.map.component.Component);
GroundOverlay.prototype.init = function (url, boundingBox) {
var that = this;
that.overlayDiv = document.createElement('div');
that.overlayDiv.style.position = 'absolute';
that.overlayDiv.style.cursor = 'default';
that.overlayImage = document.createElement('img');
that.overlayImage.id = 'groundoverlay';
that.overlayDiv.appendChild(that.overlayImage);
that.set('url', url);
that.set('boundingBox', boundingBox);
that.set('visible', true);
that.set('opacity', 1);
that.addOverlay = function () {
var isVisible = that.get('visible'),
bbox,
topLeft,
bottomRight;
if (isVisible === false) {
that.overlayDiv.style.display = 'none';
} else {
bbox = that.get('boundingBox');
topLeft = that.map.geoToPixel(bbox.topLeft);
bottomRight = that.map.geoToPixel(bbox.bottomRight);
that.overlayDiv.style.display = 'block';
that.overlayDiv.style.left = topLeft.x + 'px';
that.overlayDiv.style.top = topLeft.y + 'px';
that.overlayDiv.style.width = (bottomRight.x - topLeft.x) + 'px';
that.overlayDiv.style.height = (bottomRight.y - topLeft.y) + 'px';
that.overlayImage.src = that.get('url');
that.overlayImage.style.width = (bottomRight.x - topLeft.x) + 'px';
that.overlayImage.style.height = (bottomRight.y - topLeft.y) + 'px';
that.overlayImage.style.opacity = that.get('opacity');
}
};
that.addObserver('opacity', that.addOverlay);
that.addObserver('visible', that.addOverlay);
that.addObserver('url', that.addOverlay);
that.addObserver('boundingBox', that.addOverlay);
that.eventHandlers = {
dragListener : function (evt) {
var newGeo = that.map.pixelToGeo(
that.map.width / 2 - evt.deltaX,
that.map.height / 2 - evt.deltaY
);
that.map.set('center', newGeo);
evt.stopPropagation();
},
dblClickListener : function (evt) {
evt.target = this.parentNode.parentNode;
that.map.dispatch(evt);
},
mouseWheelListener : function (evt) {
evt.target = this.parentNode.parentNode;
that.map.dispatch(evt);
}
};
};
GroundOverlay.prototype.attach = function (map) {
this.map = map;
var controls = map.getUIContainer().firstChild,
child = controls.firstChild;
controls.insertBefore(this.overlayDiv, child);
map.addObserver('center', this.addOverlay);
map.addObserver('zoomLevel', this.addOverlay);
if (!this.evtTarget) {
this.evtTarget = nokia.maps.dom.EventTarget(
document.getElementById('groundoverlay')
).enableDrag();
this.evtTarget.addListener('drag', this.eventHandlers.dragListener);
this.evtTarget.addListener('dblclick', this.eventHandlers.dblClickListener);
this.evtTarget.addListener('mousewheel', this.eventHandlers.mouseWheelListener);
this.addOverlay();
}
};
GroundOverlay.prototype.detach = function (map) {
this.map = null;
map.removeObserver('center', this.addOverlay);
map.removeObserver('zoomLevel', this.addOverlay);
this.overlayDiv.parentNode.removeChild(this.overlayDiv);
};
GroundOverlay.prototype.getId = function () {
return 'GroundOverlay';
};
GroundOverlay.prototype.getVersion = function () {
return '1.0.0';
};

google maps listener only running once

I am having some difficulties where my listeners appear to cancel each other out only when I set a rectangle to the map, but not when I call an alert or anything else.
This works perfectly:
google.maps.event.addDomListener(document.getElementById("overlay" + me), 'click', function () {
displayMessage(me); //displays the current overlay index on screen (IE 1 of 30)
});
The above simply displays the index of the overlay on the map (IE 1 of 30). It works at every overlay clicked with the proper overlay index.
This not so much:
google.maps.event.addDomListener(document.getElementById("overlay" + me), 'click', function () {
alert("Called");
curOverlayRectangle.setOptions(overlayRectangleOptions); //defined by C# to js
curOverlayRectangle.setBounds(incomingOverlayBounds[me]);
curOverlayRectangle.setMap(map);
alert("Finished");
});
The above is supposed to add a rectangle over the overlay already on the map. What it actually does is add the rectangle for the first overlay clicked, but then if I click another overlay, nothing happens.
It appears that the listener is never called because once I click the first overlay, it goes through and says finished with the rectangle drawn. I then proceed to click another overlay and no alert occurs...
I have been working on this for quite some time, please help! Thanks!
EDIT1:
//get is simply the index
function tempAddListener(get) {
//alert("adding: " + get);
if (document.getElementById("overlay" + get) != null) { //check to see if div is there
google.maps.event.addDomListener(document.getElementById("overlay" + get), 'click', function () {
displayMessage("listener fired at overlay: " + get); //if enabled, works fine
//displayOverlayRectangle(incomingOverlayBounds[get]); //if enabled, listener fires but seems to delete all my other listeners for the overlays
});
} else {
//could not find the div
}
}
Edit2
//took out all defines
//#region geoObjs
var incomingOverlayBounds = [];
var incomingOverlaySourceURL = [];
var incomingOverlayRotation = [];
var incomingOverlayRectangle = [];
function initOverlays(){
//most of these are taken out
incomingOverlayBounds[0] = new google.maps.LatLngBounds( new google.maps.LatLng(29.7883456702236,-82.384843759249), new
incomingOverlayRotation[16] = 0;
incomingOverlayBounds[17] = new google.maps.LatLngBounds( new google.maps.LatLng(29.4715356702236,-82.3839748493845), new google.maps.LatLng(29.51265,-82.33674));
incomingOverlaySourceURL[17] = "http://ufdcimages.uflib.ufl.edu/UF/00/07/17/26/00027/12001_1968_2KK_20.jpg";
incomingOverlayRotation[17] = 0;
incomingOverlayBounds[18] = new google.maps.LatLngBounds( new google.maps.LatLng(29.4584356702236,-82.3840587432067), new google.maps.LatLng(29.49955,-82.33683));
incomingOverlaySourceURL[18] = "http://ufdcimages.uflib.ufl.edu/UF/00/07/17/26/00027/12001_1968_2KK_21.jpg";
incomingOverlayRotation[18] = 0;
incomingOverlayBounds[19] = new google.maps.LatLngBounds( new google.maps.LatLng(29.4431556702236,-82.4158516259991), new google.maps.LatLng(29.48427,-82.36863));
incomingOverlaySourceURL[19] = "http://ufdcimages.uflib.ufl.edu/UF/00/07/17/26/00027/12001_1968_2KK_022.jpg";
incomingOverlayRotation[19] = 0;
incomingOverlayBounds[20] = new google.maps.LatLngBounds( new google.maps.LatLng(29.4593656702236,-82.4157191765652), new google.maps.LatLng(29.50048,-82.36849));
incomingOverlaySourceURL[20] = "http://ufdcimages.uflib.ufl.edu/UF/00/07/17/26/00027/12001_1968_2KK_023.jpg";
incomingOverlayRotation[20] = 0;
incomingOverlayBounds[21] = new google.maps.LatLngBounds( new google.maps.LatLng(29.4736856702236,-82.4151858519302), new google.maps.LatLng(29.5148,-82.36795));
incomingOverlaySourceURL[21] = "http://ufdcimages.uflib.ufl.edu/UF/00/07/17/26/00027/12001_1968_2KK_024.jpg";
incomingOverlayRotation[21] = 0;
incomingOverlaySourceURL[51] = "http://ufdcimages.uflib.ufl.edu/UF/00/07/17/26/00027/12001_1968_2KK_054.jpg";
incomingOverlayRotation[51] = 0;
displayIncomingOverlays();
}
//#endregion
function initialize() {
//initialize google map objects
map = new google.maps.Map(document.getElementById(gmapPageDivId), gmapOptions); //initialize map
initOverlays(); //initialize all the incoming overlays
}
var incomingOverlayBounds = [];
var incomingOverlaySourceURL = [];
var incomingOverlayRotation = [];
var overlays = [];
function displayIncomingOverlays() {
for (var i = 0; i < incomingOverlayBounds.length; i++) {
overlaysOnMap[i] = new CustomOverlay(incomingOverlayBounds[i], incomingOverlaySourceURL[i], map, incomingOverlaySourceURL[i]);
overlaysOnMap[i].setMap(map);
//displayOverlayRectangle(incomingOverlayBounds[i]); //add all the rectangles
}
}
function CustomOverlay(bounds, image, map, rotation) {
//iterate here
overlayCount++;
// Now initialize all properties.
this.bounds_ = bounds;
this.image_ = image;
this.map_ = map;
preservedRotation = rotation;
if (overlayPrevious != null) {
overlayPrevious.setMap(null);
}
// We define a property to hold the image's div. We'll
// actually create this div upon receipt of the onAdd()
// method so we'll leave it null for now.
this.div_ = null;
}
CustomOverlay.prototype.onAdd = function () {
if (overlayPrevious != null) {
overlayPrevious.setMap(null);
}
// Note: an overlay's receipt of onAdd() indicates that
// the map's panes are now available for attaching
// the overlay to the map via the DOM.
// Create the DIV and set some basic attributes.
var div = document.createElement("div");
div.id = "overlay" + overlaysOnMap.indexOf(this);
div.style.borderStyle = 'none';
div.style.borderWidth = '0px';
div.style.position = 'absolute';
div.style.opacity = preserveOpacity;
// Create an IMG element and attach it to the DIV.
var img = document.createElement('img');
img.src = incomingOverlaySourceURL[overlaysOnMap.indexOf(this)]; //this.image
img.style.width = '100%';
img.style.height = '100%';
img.style.position = 'absolute';
div.appendChild(img);
//get the index
var overlayIndex = overlaysOnMap.indexOf(this);
// Set the overlay's div_ property to this DIV
this.div_ = div;
// We add an overlay to a map via one of the map's panes.
// We'll add this overlay to the overlayLayer pane.
var panes = this.getPanes();
panes.overlayLayer.appendChild(div);
//add the listener
tempAddListener(overlayIndex);
};
CustomOverlay.prototype.draw = function () {
// Size and position the overlay. We use a southwest and northeast
// position of the overlay to peg it to the correct position and size.
// We need to retrieve the projection from this overlay to do this.
var overlayProjection = this.getProjection();
// Retrieve the southwest and northeast coordinates of this overlay
// in latlngs and convert them to pixels coordinates.
// We'll use these coordinates to resize the DIV.
var sw = overlayProjection.fromLatLngToDivPixel(this.bounds_.getSouthWest());
var ne = overlayProjection.fromLatLngToDivPixel(this.bounds_.getNorthEast());
// Resize the image's DIV to fit the indicated dimensions.
var div = this.div_;
div.style.left = sw.x + 'px';
div.style.top = ne.y + 'px';
div.style.width = (ne.x - sw.x) + 'px';
div.style.height = (sw.y - ne.y) + 'px';
//for a preserved rotation
if (preservedRotation != 0) {
//keepRotate(preservedRotation);
}
};
//CustomOverlay.prototype.onRemove = function () {
// this.div_.parentNode.removeChild(this.div_);
// this.div_ = null;
//};
function tempAddListener(get) {
alert("div: "+document.getElementById("overlay" + get).innerHTML);
alert("adding with index: " + get);
if (document.getElementById("overlay" + get) != null) { //check to see if div is there
google.maps.event.addDomListener(document.getElementById("overlay" + get), 'click', function () {
alert("listener fired at overlay: " + get);
displayOverlayRectangle(incomingOverlayBounds[get]);
//alert(incomingOverlayBounds[get]);
//overlayRectangles[get] = displayOverlayRectangle(incomingOverlayBounds[get]);
//overlayRectangles[get].setMap(map);
});
} else {
//could not find the div
}
}
function displayOverlayRectangle(bounds) {
//2do: set drawing manager, set mode, match listeners of rectangle
var tempOverlayRectangle = new google.maps.Rectangle();
var tempOverlayRectangleOptions = {
strokeColor: "#FF0000",
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#FF0000",
fillOpacity: 0.1,
editable: true,
draggable: true,
//strokeOpacity: 0.2,
//strokeWeight: 1,
//fillOpacity: 0.0,
zindex: 5
};
tempOverlayRectangle.setOptions(tempOverlayRectangleOptions);
tempOverlayRectangle.setBounds(bounds);
tempOverlayRectangle.setMap(map);
google.maps.event.addListener(tempOverlayRectangle, "click", function () {
alert("can't touch this");
});
//return tempOverlayRectangle;
//tempOverlayRectangle.setOptions(tempOverlayRectangleOptions);
//tempOverlayRectangle.setBounds(bounds);
//tempOverlayRectangle.setMap(map);
}
//start this whole mess once
google.maps.event.addDomListener(window, 'load', initialize);
</script>
<div id="googleMap"></div>
UPDATE
It appears that any map code on the listener will invalidate the other listeners. (IE I tried it with the following code and it still only ran once)
google.maps.event.addDomListener(document.getElementById("overlay" + get), 'click', function () {
if (map.getMapTypeId() == 'TERRAIN') {
map.setMapTypeId(google.maps.MapTypeId.ROADMAP);
} else {
map.setMapTypeId(google.maps.MapTypeId.TERRAIN);
}
});
SOLVED
Bottom line, the overlay I was creating could not be accessed appropriately by the DOM. Thus, I created an invisible rectangle to overlay on top of my overlay which can be accessed.
Snippet:
var incomingOverlayBounds = []; //defined in c# to js on page
var incomingOverlaySourceURL = []; //defined in c# to js on page
var incomingOverlayRotation = []; //defined in c# to js on page
var ghostOverlayRectangle = []; //holds ghost overlay rectangles (IE overlay hotspots)
var ghostOverlayRectangleOptions = { //define options for ghost rectangle
strokeColor: "#FF0000", //color doesnt matter
strokeOpacity: 0.0, //make border invisible
strokeWeight: 1, //should not matter?
fillColor: "#FF0000", //color doesnt matter
fillOpacity: 0.0, //make fill transparent
editable: false, //just to be sure?
draggable: false, //just to be sure?
zindex: 6 //perhaps higher?
};
var visibleOverlayRectangleOptions = { //define options for visible rectangle
strokeColor: "#FF0000", //for testing (red)
strokeOpacity: 0.8, //for testing
strokeWeight: 2, //for testing
fillColor: "#FF0000", //for testing (red)
fillOpacity: 0.1, //for testing
editable: true, //sobek standard
draggable: true, //sobek standard
//strokeOpacity: 0.2, //sobek standard
//strokeWeight: 1, //sobek standard
//fillOpacity: 0.0, //sobek standard
zindex: 5 //sobek standard
};
var visibleOverlayRectangle = new google.maps.Rectangle(); //init maybe move to array later
//Displays all the overlays sent from the C# code. Also calls displayGhostOverlayRectangle.
function displayIncomingOverlays() {
//go through and display overlays as long as there is an overlay to display
for (var i = 0; i < incomingOverlayBounds.length; i++) {
overlaysOnMap[i] = new CustomOverlay(incomingOverlayBounds[i], incomingOverlaySourceURL[i], map, incomingOverlayRotation[i]);
overlaysOnMap[i].setMap(map); //set the overlay to the map
displayGhostOverlayRectangle(incomingOverlayBounds[i],i); //add all the ghost rectangles
}
}
//Displays an invisible rectangle on top of the overlay div (creates a hotspot). This rectangle is used as a psuedo listener if the 'overlay div' is clicked. This solved issue of creating listener for overlay div directly.
//Supporting URL: http://stackoverflow.com/questions/17025240/google-maps-listener-only-running-once
function displayGhostOverlayRectangle(ghostBounds,ghostIndex) {
ghostOverlayRectangle[ghostIndex] = new google.maps.Rectangle(); //init rect
ghostOverlayRectangle[ghostIndex].setOptions(ghostOverlayRectangleOptions); //set options
ghostOverlayRectangle[ghostIndex].setBounds(ghostBounds); //set bounds
ghostOverlayRectangle[ghostIndex].setMap(map); //set to map
//create the listener for this ghost rectangle
google.maps.event.addListener(ghostOverlayRectangle[ghostIndex], 'click', function () {
displayVisibleOverlayRectangle(ghostBounds, ghostIndex); //add the visible rectangles
});
}
//Displays the visible rectangle which is used to edit an overlay. Called by the ghost listener.
function displayVisibleOverlayRectangle(bounds, overlayIndex) {
visibleOverlayRectangle.setOptions(visibleOverlayRectangleOptions);
visibleOverlayRectangle.setBounds(bounds);
visibleOverlayRectangle.setMap(map);
}
//Starts the creation of a custom overlay div which contains a rectangular image.
//Supporting URL: https://developers.google.com/maps/documentation/javascript/overlays#CustomOverlays
function CustomOverlay(bounds, image, map, rotation) {
overlayCount++; //iterate how many overlays have been drawn
this.bounds_ = bounds; //set the bounds
this.image_ = image; //set source url
this.map_ = map; //set to map
preservedRotation = rotation; //set the rotation
this.div_ = null; //defines a property to hold the image's div. We'll actually create this div upon receipt of the onAdd() method so we'll leave it null for now.
}
//Continues support for adding an custom overlay
//Supporting URL: https://developers.google.com/maps/documentation/javascript/overlays#CustomOverlays
// Note: an overlay's receipt of onAdd() indicates that the map's panes are now available for attaching the overlay to the map via the DOM.
CustomOverlay.prototype.onAdd = function () {
// Create the DIV and set some basic attributes.
var div = document.createElement("div");
div.id = "overlay" + overlaysOnMap.indexOf(this);
div.style.borderStyle = 'none';
div.style.borderWidth = '0px';
div.style.position = 'absolute';
div.style.opacity = preserveOpacity;
// Create an IMG element and attach it to the DIV.
var img = document.createElement('img');
img.src = incomingOverlaySourceURL[overlaysOnMap.indexOf(this)]; //this.image
img.style.width = '100%';
img.style.height = '100%';
img.style.position = 'absolute';
div.appendChild(img);
// Set the overlay's div_ property to this DIV
this.div_ = div;
// We add an overlay to a map via one of the map's panes.
// We'll add this overlay to the overlayLayer pane.
var panes = this.getPanes();
panes.overlayLayer.appendChild(div);
};
//Continues support for adding an custom overlay
//Supporting URL: https://developers.google.com/maps/documentation/javascript/overlays#CustomOverlays
CustomOverlay.prototype.draw = function () {
// Size and position the overlay. We use a southwest and northeast
// position of the overlay to peg it to the correct position and size.
// We need to retrieve the projection from this overlay to do this.
var overlayProjection = this.getProjection();
// Retrieve the southwest and northeast coordinates of this overlay
// in latlngs and convert them to pixels coordinates.
// We'll use these coordinates to resize the DIV.
var sw = overlayProjection.fromLatLngToDivPixel(this.bounds_.getSouthWest());
var ne = overlayProjection.fromLatLngToDivPixel(this.bounds_.getNorthEast());
// Resize the image's DIV to fit the indicated dimensions.
var div = this.div_;
div.style.left = sw.x + 'px';
div.style.top = ne.y + 'px';
div.style.width = (ne.x - sw.x) + 'px';
div.style.height = (sw.y - ne.y) + 'px';
//for a preserved rotation
if (preservedRotation != 0) {
keepRotate(preservedRotation);
}
};
//Not currently used
//Supporting URL: https://developers.google.com/maps/documentation/javascript/overlays#CustomOverlays
CustomOverlay.prototype.onRemove = function () {
this.div_.parentNode.removeChild(this.div_);
this.div_ = null;
};

Circle radius with Driving Directions in Bing Maps

I'm currently developing a web site that are using Bing Maps. I'm using the Bing Maps Version 7. I have created a fully functional driving directions function. Which works like this:
The user rightclicks on the map, where doesn't matter. Then a context menu is brought up, where the user can chose between two alternatives. Which is: Align Start and Align Finish.
As you might understand those functions are creating a way-point on the locations of where the user right-clicked. Also a radius circle is aligned on respective way-point. Both start and finish way-points are dragable / movable, which means that the user can move the way-points around. The problem is that when the user moves one of the way-points the radius circle isn't moving also, which not is weird because I have not created a function for that yet. I don't think that is hard to do, but I don't know how to get the new position of the moved way-point. I'm posting my code. So I do really need some help with making this "RadiusCircleMove".
Here is my Javascript Code:
var map = null;
var directionsManager;
var directionsErrorEventObj;
var directionsUpdatedEventObj;
var startPosition;
var checkpointPosition;
var finishPosition;
var popuplat;
var popuplon;
var waypointType;
var startcircle;
var checkpointcircle;
var finishcircle;
var startcirclelat;
var startcirclelon;
var checkpointcirclelat;
var checkpointcirclelon;
var finishcirclelat;
var finishcirclelon;
$(document).ready(function () {
//this one line will disable the right mouse click menu
$(document)[0].oncontextmenu = function () { return false; }
GetMap();
});
function GetMap() {
map = new Microsoft.Maps.Map(document.getElementById("myMap"), { credentials: "Enter Bing Key Here", zoom: 4, center: new Microsoft.Maps.Location(45, -100) });
Microsoft.Maps.registerModule("BMv7.AdvancedShapes", "BMv7.AdvancedShapes.min.js");
Microsoft.Maps.loadModule("BMv7.AdvancedShapes");
//map.AttachEvent("onclick", ShowPopupMenu);
Microsoft.Maps.Events.addHandler(map, 'click', RemovePopupMenu);
Microsoft.Maps.Events.addHandler(map, 'rightclick', ShowPopupMenu);
}
function ShowPopupMenu(e) {
var point = new Microsoft.Maps.Point(e.getX(), e.getY());
popuplat = e.target.tryPixelToLocation(point).latitude
popuplon = e.target.tryPixelToLocation(point).longitude
var menu = document.getElementById('popupmenu');
menu.style.display = 'block'; //Showing the menu
menu.style.left = e.pageX + "px"; //Positioning the menu
menu.style.top = e.pageY + "px";
}
function RemovePopupMenu() {
document.getElementById("popupmenu").style.display = 'none';
}
function createDirectionsManager() {
var displayMessage;
if (!directionsManager) {
directionsManager = new Microsoft.Maps.Directions.DirectionsManager(map);
//displayMessage = 'Directions Module loaded\n';
//displayMessage += 'Directions Manager loaded';
}
//alert(displayMessage);
directionsManager.resetDirections();
directionsUpdatedEventObj = Microsoft.Maps.Events.addHandler(directionsManager, 'directionsUpdated', function () {} );
}
function createDrivingRoute() {
if (!directionsManager) { createDirectionsManager(); }
directionsManager.resetDirections();
// Set Route Mode to driving
directionsManager.setRequestOptions({ routeMode: Microsoft.Maps.Directions.RouteMode.driving });
if (waypointType == "start") {
addDefaultPushpin();
startPosition = new Microsoft.Maps.Directions.Waypoint({ location: new Microsoft.Maps.Location(popuplat, popuplon) });
startcirclelat = popuplat;
startcirclelon = popuplon;
}
if (waypointType == "checkpoint") {
addDefaultPushpin();
checkpointPosition = new Microsoft.Maps.Directions.Waypoint({ location: new Microsoft.Maps.Location(popuplat, popuplon) });
checkpointcirclelat = popuplat;
checkpointcirclelon = popuplon;
}
if (waypointType == "finish") {
finishPosition = new Microsoft.Maps.Directions.Waypoint({ location: new Microsoft.Maps.Location(popuplat, popuplon) });
finishcirclelat = popuplat;
finishcirclelon = popuplon;
directionsManager.addWaypoint(startPosition);
directionsManager.addWaypoint(checkpointPosition);
directionsManager.addWaypoint(finishPosition);
directionsManager.calculateDirections();
deletePushpin();
CreateStartCircle();
CreateCheckpointCircle();
CreateFinishCircle();
}
// Set the element in which the itinerary will be rendered
directionsManager.setRenderOptions({ itineraryContainer: document.getElementById('directionsItinerary') });
//alert('Calculating directions...');
}
function createDirections() {
if (!directionsManager) {
Microsoft.Maps.loadModule('Microsoft.Maps.Directions', { callback: createDrivingRoute });
}
else {
createDrivingRoute();
}
}
function AddStartPosition() {
waypointType = "start";
createDirections();
RemovePopupMenu();
}
function AddCheckpointPosition() {
waypointType = "checkpoint";
createDirections();
RemovePopupMenu();
}
function AddFinishPosition() {
waypointType = "finish";
createDirections();
RemovePopupMenu();
}
function addDefaultPushpin() {
var pushpin = new Microsoft.Maps.Pushpin(new Microsoft.Maps.Location(popuplat, popuplon));
map.entities.push(pushpin);
}
function deletePushpin() {
for (var i = map.entities.getLength() - 1; i >= 0; i--) {
var pushpin = map.entities.get(i);
if (pushpin instanceof Microsoft.Maps.Pushpin) {
map.entities.removeAt(i);
};
}
}
function CreateStartCircle() {
startcircle = DecStartCircle();
map.entities.push(startcircle);
}
function CreateCheckpointCircle() {
checkpointcircle = DecCheckpointCircle();
map.entities.push(checkpointcircle);
}
function CreateFinishCircle() {
finishcircle = DecFinishCircle();
map.entities.push(finishcircle);
}
/***** Start Circle ****/
function DecStartCircle() {
var polygonOptions = {
fillColor: new Microsoft.Maps.Color(100, 0, 0, 255),
strokeColor: new Microsoft.Maps.Color(100, 255, 0, 0)
};
return new BMv7.AdvanceShapes.Circle(new Microsoft.Maps.Location(startcirclelat, startcirclelon), 80000, polygonOptions);
}
/***** Checkpoint Circle ****/
function DecCheckpointCircle() {
var polygonOptions = {
fillColor: new Microsoft.Maps.Color(100, 0, 0, 255),
strokeColor: new Microsoft.Maps.Color(100, 255, 0, 0)
};
return new BMv7.AdvanceShapes.Circle(new Microsoft.Maps.Location(checkpointcirclelat, checkpointcirclelon), 80000, polygonOptions);
}
/***** Finish Circle ****/
function DecFinishCircle() {
var polygonOptions = {
fillColor: new Microsoft.Maps.Color(100, 0, 0, 255),
strokeColor: new Microsoft.Maps.Color(100, 255, 0, 0)
};
return new BMv7.AdvanceShapes.Circle(new Microsoft.Maps.Location(finishcirclelat, finishcirclelon), 80000, polygonOptions);
}
I believe you need to actually implement your DirectionsUpdated event. Your code contains the following empty function:
directionsUpdatedEventObj = Microsoft.Maps.Events.addHandler(directionsManager, 'directionsUpdated', function () {} );
You shouldn't be doing anything with the map until the directions have completed loading. Once they have loaded, then you can do the following:
Clear all map entities map.entities.clear(); which removes all previous polylines and polygons
Then reset directions: directionsManager.resetDirections(); to clear the current directions (otherwise you'll see waypoints appended).
Then get all of the waypoints from the directions module directionsManager.getAllWaypoints();
Now plot your three circles.
Your problem is one of timing and correct sequencing.

Prevent google overlay/infowindow from allowing clicks through to markers underneath

I'm trying to make some custom Google maps info windows, but I'm getting the issue where markers underneath my custom info window is clickable through the info window.
Here's an example (basically straight from googles example here)
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<title>Google Maps JavaScript API v3 Example: Info Window Custom</title>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
/* An InfoBox is like an info window, but it displays
* under the marker, opens quicker, and has flexible styling.
* #param {GLatLng} latlng Point to place bar at
* #param {Map} map The map on which to display this InfoBox.
* #param {Object} opts Passes configuration options - content,
* offsetVertical, offsetHorizontal, className, height, width
*/
function InfoBox(opts) {
google.maps.OverlayView.call(this);
this.latlng_ = opts.latlng;
this.map_ = opts.map;
this.offsetVertical_ = -195;
this.offsetHorizontal_ = 0;
this.height_ = 165;
this.width_ = 266;
var me = this;
this.boundsChangedListener_ =
google.maps.event.addListener(this.map_, "bounds_changed", function() {
return me.panMap.apply(me);
});
// Once the properties of this OverlayView are initialized, set its map so
// that we can display it. This will trigger calls to panes_changed and
// draw.
this.setMap(this.map_);
}
/* InfoBox extends GOverlay class from the Google Maps API
*/
InfoBox.prototype = new google.maps.OverlayView();
/* Creates the DIV representing this InfoBox
*/
InfoBox.prototype.remove = function() {
if (this.div_) {
this.div_.parentNode.removeChild(this.div_);
this.div_ = null;
}
};
/* Redraw the Bar based on the current projection and zoom level
*/
InfoBox.prototype.draw = function() {
// Creates the element if it doesn't exist already.
this.createElement();
if (!this.div_) return;
// Calculate the DIV coordinates of two opposite corners of our bounds to
// get the size and position of our Bar
var pixPosition = this.getProjection().fromLatLngToDivPixel(this.latlng_);
if (!pixPosition) return;
// Now position our DIV based on the DIV coordinates of our bounds
this.div_.style.width = this.width_ + "px";
this.div_.style.left = (pixPosition.x + this.offsetHorizontal_) + "px";
this.div_.style.height = this.height_ + "px";
this.div_.style.top = (pixPosition.y + this.offsetVertical_) + "px";
this.div_.style.display = 'block';
};
/* Creates the DIV representing this InfoBox in the floatPane. If the panes
* object, retrieved by calling getPanes, is null, remove the element from the
* DOM. If the div exists, but its parent is not the floatPane, move the div
* to the new pane.
* Called from within draw. Alternatively, this can be called specifically on
* a panes_changed event.
*/
InfoBox.prototype.createElement = function() {
var panes = this.getPanes();
var div = this.div_;
if (!div) {
// This does not handle changing panes. You can set the map to be null and
// then reset the map to move the div.
div = this.div_ = document.createElement("div");
div.style.border = "0px none";
div.style.position = "absolute";
div.style.background = "url('http://gmaps-samples.googlecode.com/svn/trunk/images/blueinfowindow.gif')";
div.style.width = this.width_ + "px";
div.style.height = this.height_ + "px";
var contentDiv = document.createElement("div");
contentDiv.style.padding = "30px"
contentDiv.innerHTML = "<b>Hello World!</b>";
var topDiv = document.createElement("div");
topDiv.style.textAlign = "right";
var closeImg = document.createElement("img");
closeImg.style.width = "32px";
closeImg.style.height = "32px";
closeImg.style.cursor = "pointer";
closeImg.src = "http://gmaps-samples.googlecode.com/svn/trunk/images/closebigger.gif";
topDiv.appendChild(closeImg);
function removeInfoBox(ib) {
return function() {
ib.setMap(null);
};
}
google.maps.event.addDomListener(closeImg, 'click', removeInfoBox(this));
div.appendChild(topDiv);
div.appendChild(contentDiv);
div.style.display = 'none';
panes.floatPane.appendChild(div);
this.panMap();
} else if (div.parentNode != panes.floatPane) {
// The panes have changed. Move the div.
div.parentNode.removeChild(div);
panes.floatPane.appendChild(div);
} else {
// The panes have not changed, so no need to create or move the div.
}
}
/* Pan the map to fit the InfoBox.
*/
InfoBox.prototype.panMap = function() {
};
function initialize() {
var myOptions = {
zoom: 8,
center: new google.maps.LatLng(-33.397, 150.644),
mapTypeId: google.maps.MapTypeId.ROADMAP,
sensor: 'true'
}
var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
var marker = new google.maps.Marker({
position: new google.maps.LatLng(-34, 150),
map: map
});
google.maps.event.addListener(marker, "click", function(e) {
var infoBox = new InfoBox({latlng: marker.getPosition(), map: map});
});
var m2 = new google.maps.Marker({
position: new google.maps.LatLng(-33.5, 150.5),
map: map
});
google.maps.event.addListener(m2, "click", function(e) {
var infoBox = new InfoBox({latlng: m2.getPosition(), map: map});
});
}
</script>
</head>
<body style="margin:0px; padding:0px;" onload="initialize()">
<div id="map_canvas" style="width:100%; height:100%"></div>
</body>
</html>
You can see I'm making two markers, one just to the north east of the other. Click the bottom one then observe how the other marker is clickable through the marker (right near the 'W').
How can I fix this?! I've tried altering the z-index but that didn't seem to help.
This is using api v3 btw.
For posterity, you want to disable a bunch of events on the marker pop-up dom, this was the prescribed method, even though it feels like overkill. You could alternatively cycle through all the markers present apart from the one clicked and disable clicking on them (actually that's probably a better solution in hindsight). Depends on how many markers you have perhaps, I had a lot.
Something like this (transcribed here without testing from my coffeescript so...)
// All in a google.maps.OverlayView subclass.
...
this.listeners = new Array(); // save listeners for unbinding later
...
this.cancelEvents = function(){
events = ['mousedown', 'mousemove', 'mouseover',
'mouseout', 'mouseup', 'mousewheel',
'DOMMouseScroll', 'touchstart', 'touchend',
'touchmove', 'dblclick', 'contextmenu'];
// Note, don't disable 'click' if you want to be able to click links in the dom. Some things we're disabling here will can effect how your user might interact with the popup (double click to select text etc)
for(var i = 0; i < events.length; i++){
var event = events[i];
this.listeners.push(
google.maps.event.addDomListener(
this.popup_dom_element,
event,
function(ev){
e.cancelBubble = true;
if(e.stopPropagation){
e.stopPropagation();
}
}
);
);
}
}
this.onAdd = function (){
// build your html popup
var html_code = "...";
// easy way to get a dom element but probably over kill if its your only JQ
this.popup_dom_element = $(html_code);
this.cancelEvents();
}
this.onRemove = function(){
// any other removal code you have
...
for(var i = 0; i < this.listeners.length; i++){
// remove our event listeners
google.maps.event.removeListener(this.listeners[i]);
}
}
Try and use the MapPane overlayMouseTarget instead of floatPane.
If you don't want people to be able to click on a marker, could you call marker.setClickable(false)
i had the same problem and its actually very easy:/
if u are using jquery just set
$(div).bind("click",function(e) {
return false;
});
in the InfoBox.prototype.createElement function. This should help.
Cheers
use:
google.maps.event.addDomListener
instead of
google.maps.event.addListener

Categories