How to target element on a Google Maps custom InfoBox? - javascript

I have created a custom close button for the InfoBox, but I cannot get it to close. I have tried to create an eventlistener for when the box is clicked, but no luck so far. The code is as follows:
InfoPopupbox.prototype = new google.maps.OverlayView();
InfoPopupbox.prototype.onAdd = function() {
//add is after the map has been initiated
var div = document.createElement('div');
var classname = "infoWrapper ";
if (this.customclass){
classname += this.customclass;
}
div.className = classname ;
div.style.border = "none";
div.style.borderWidth = "0px";
div.style.position = "absolute";
div.appendChild(this.content_);
this.div_ = div;
var panes = this.getPanes();
//panes.overlayLayer.appendChild(div);
//float the Pane above the map
panes.floatPane.appendChild(div);
google.maps.event.addListener( this , 'click' , function(){
console.log('click close');
that.infotoggle();
});
};

You want to use addDomListener instead of addListener for click, and you'll need to bind it to the DOM Element:
google.maps.event.addDomListener(this.div, 'click', function() { ... });

Related

Click handler not working for <div> with <object> as child

I have just two elements, a div with an object attached as child, which contains an SVG image. The click handler works fine when there is just the div by itself, or another tag as it's child, such as img. However, when the object is a child, the div click handler is only triggered in the very bottom right corner. I'm really stuck as to what would be causing this behavior.
let divContainer = document.createElement('div');
divContainer.className = 'divContainer';
divContainer.style.position = 'absolute'
divContainer.style.top = '100px';
divContainer.style.width = '150px';
divContainer.style.height = '150px';
divContainer.style.background = 'green';
let imageChild = document.createElement('object');
imageChild.type = 'image/svg+xml';
imageChild.data = 'https://svgsilh.com/svg_v2/48363.svg'
imageChild.className = 'imageChild';
imageChild.style.width = 'inherit';
document.body.append(divContainer);
// Comment this out, and it works fine
divContainer.append(imageChild);
divContainer.onclick = function(event) {
console.log('Click OK!');
}
here is the working code
let divContainer = document.createElement('div');
divContainer.className = 'divContainer';
divContainer.style.top = '100px';
divContainer.style.width = '150px';
divContainer.style.height = '150px';
divContainer.style.background = 'green';
let imageChild = document.createElement('object');
imageChild.type = 'image/svg+xml';
imageChild.data = 'https://svgsilh.com/svg_v2/48363.svg';
imageChild.className = 'imageChild';
imageChild.style.width = 'inherit';
imageChild.style.pointerEvents = 'none';
document.body.append(divContainer);
// Comment this out, and it works fine
divContainer.append(imageChild);
divContainer.addEventListener('click', function () {
alert('Click OK!');
});

Google 3.32 causes MapOverlay error

Everything works fine using 3.31, but when I use the 3.32 or 3.33 script my overlay fails to load. Here is my custom overlay class:
function MapOverlay(bounds, image, map) {
// Now initialize all properties.
var sw = new google.maps.LatLng(bounds.southWest.latitude, bounds.southWest.longitude);
var ne = new google.maps.LatLng(bounds.northEast.latitude, bounds.northEast.longitude);
//if (westernCorner.longitude > easternCorner.longitude)
this.bounds = new google.maps.LatLngBounds(sw, ne);
this.image = image;
this.map = map;
// We define a property to hold the image's
// div. We'll actually create this div
// upon receipt of the add() method so we'll
// leave it null for now.
this.div = null;
// Explicitly call setMap() on this overlay
this.setMap(map);
}
MapOverlay.prototype = new google.maps.OverlayView();
MapOverlay.prototype.onAdd = function() {
// 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.style.border = "none";
div.style.borderWidth = "0px";
div.style.position = "absolute";
// Create an IMG element and attach it to the DIV.
var img = document.createElement("img");
img.src = this.image;
img.style.width = "100%";
img.style.height = "100%";
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 overlayImage pane.
var panes = this.getPanes();
panes.overlayLayer.appendChild(div);
};
MapOverlay.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';
console.log("ne.x: " + ne.x + " sw.x " + sw.x + " width: " + (ne.x - sw.x));
div.style.width = (ne.x - sw.x) + 'px';
div.style.height = (sw.y - ne.y) + 'px';
};
MapOverlay.prototype.onRemove = function() {
this.div.parentNode.removeChild(this.div);
this.div = null;
};
// Note that the visibility property must be a string enclosed in quotes
MapOverlay.prototype.hide = function() {
if (this.div) {
this.div.style.visibility = "hidden";
}
};
MapOverlay.prototype.show = function() {
if (this.div) {
this.div.style.visibility = "visible";
}
};
And here is where the overlay is set up:
addImageOverlay: function(bounds, url, hidden) {
var ne = new google.maps.LatLng(bounds.northEast.latitude,
bounds.northEast.longitude);
var sw = new google.maps.LatLng(bounds.southWest.latitude,
bounds.southWest.longitude);
var b = new google.maps.LatLngBounds(sw, ne);
if(this.imageOverlay){
this.imageOverlay.setMap(null);
this.imageOverlay = null;
}
this.imageOverlay = new MapOverlay(bounds, url, this.map);
this.imageOverlay.setMap(this.map);
if (hidden === true) {
this.imageOverlay.setMap(null);
} else {
this.imageOverlay.setMap(this.map);
}
return this.imageOverlay;
}
The error I am getting is:
Cannot read property 'parentNode' of null
at MapOverlay.onRemove (MapOverlay.js:90)
From what I can tell so far, the onAdd() method does not appear to be getting called when I call setMap(map). Therefore, this.div is null when onRemove() is called (thus the NPE). Map is populated and valid as far as I can tell. Again, this is only happening in 3.32 and 3.33 of Google Maps API. I can't find any change in the documentation that would be causing this and have been stuck for a day now. I can stick with 3.31 for now, but it is supposedly being sunset in August.
MapOverlay.prototype.onRemove = function() {
if (this.div && this.div.parentNode) {
this.div.parentNode.removeChild(this.div);
}
this.div = null;
};
Added IF block and this will solves problem.
Please find the reference link below:-
1. https://github.com/googlemaps/v3-utility-library/issues/393
2. https://github.com/enyo/dropzone/issues/1083

leaflet Js custom control button add (text, hover)

I followed this control-button-leaflet tutorial and it worked for me. Now I want to:
show some text when i hover over the button (like with the zoom buttons)
Change the color of the button when i hover over it
be able to write text inside the button instead of an image.
Here's the code:
var customControl = L.Control.extend({
options: {
position: 'topleft'
},
onAdd: function (map) {
var container = L.DomUtil.create('div', 'leaflet-bar leaflet-control leaflet-control-custom');
container.style.backgroundColor = 'white';
container.style.backgroundImage = "url(http://t1.gstatic.com/images?q=tbn:ANd9GcR6FCUMW5bPn8C4PbKak2BJQQsmC-K9-mbYBeFZm1ZM2w2GRy40Ew)";
container.style.backgroundSize = "30px 30px";
container.style.width = '30px';
container.style.height = '30px';
container.onclick = function(){
console.log('buttonClicked');
}
return container;
}
});
var map;
var readyState = function(e){
map = new L.Map('map').setView([48.935, 18.14], 14);
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
map.addControl(new customControl());
}
window.addEventListener('DOMContentLoaded', readyState);
It seems you more need a Button than a div:
var container = L.DomUtil.create('input');
container.type="button";
Then you can easily set a mouseover text:
container.title="No cat";
And some Text instead of an image:
container.value = "42";
And you can use the mouse events to style the button:
container.onmouseover = function(){
container.style.backgroundColor = 'pink';
}
container.onmouseout = function(){
container.style.backgroundColor = 'white';
}
(you could of course do this last part with css, might be more elegant)
Full example: http://codepen.io/anon/pen/oXVMvy

Using Google Maps custom overlays to create custom icons (with Raphael JS)

I'm using Google Maps OverlayView class to create custom markers (with Raphael JS) and am having issues accessing certain properties of my new subclass when calling a public method.
I followed Google's fairly straightforward example here ~ https://developers.google.com/maps/documentation/javascript/overlays#CustomOverlays ~ to create a custom marker class, including its 'hide' and 'show' methods.
function MapCustomMarker(opts){
this.pos_ = opts.position;
this.map_ = opts.map;
this.div_ = null;
this.color_ = (!opts.color ? '#e32636' : opts.color);
this.height_ = 32;
this.width_ = 32;
this.scale_ = 1.2;
this.icons_ = {
pinpoint:'M16,3.5c-4.142,0-7.5,3.358-7.5,7.5c0,4.143,7.5,18.121,7.5,18.121S23.5,15.143,23.5,11C23.5,6.858,20.143,3.5,16,3.5z M16,14.584c-1.979,0-3.584-1.604-3.584-3.584S14.021,7.416,16,7.416S19.584,9.021,19.584,11S17.979,14.584,16,14.584z',
help: 'M12.558,15.254c2.362,0,4.277-1.916,4.277-4.279s-1.916-4.279-4.277-4.279c-2.363,0-4.28,1.916-4.28,4.279S10.194,15.254,12.558,15.254zM15.662,15.224c-0.875,0.641-1.941,1.031-3.103,1.031c-1.164,0-2.231-0.391-3.105-1.031c-0.75,0.625-1.498,1.519-2.111,2.623c-1.422,2.563-1.578,5.192-0.35,5.874c0.55,0.312,1.127,0.078,1.723-0.496c-0.105,0.582-0.166,1.213-0.166,1.873c0,2.938,1.139,5.312,2.543,5.312c0.846,0,1.265-0.865,1.466-2.188c0.201,1.311,0.62,2.188,1.462,2.188c1.396,0,2.544-2.375,2.544-5.312c0-0.66-0.062-1.291-0.167-1.873c0.598,0.574,1.174,0.812,1.725,0.496c1.228-0.682,1.069-3.311-0.353-5.874C17.159,16.742,16.412,15.849,15.662,15.224zM19.821,3.711l-1.414,1.414c1.499,1.499,2.428,3.569,2.428,5.851c0,2.283-0.929,4.353-2.428,5.853l1.413,1.412c1.861-1.86,3.015-4.43,3.015-7.265C22.835,8.142,21.683,5.572,19.821,3.711zM16.288,14.707l1.413,1.414c1.318-1.318,2.135-3.138,2.135-5.145c0-2.007-0.816-3.827-2.134-5.145l-1.414,1.414c0.956,0.956,1.547,2.275,1.547,3.731S17.243,13.751,16.288,14.707zM21.941,1.59l-1.413,1.414c2.042,2.042,3.307,4.862,3.307,7.971c0,3.11-1.265,5.93-3.308,7.972l1.413,1.414c2.405-2.404,3.895-5.725,3.895-9.386C25.835,7.315,24.346,3.995,21.941,1.59z'
}
this.popup_ = 'M16,5.333c-7.732,0-14,4.701-14,10.5c0,1.982,0.741,3.833,2.016,5.414L2,25.667l5.613-1.441c2.339,1.317,5.237,2.107,8.387,2.107c7.732,0,14-4.701,14-10.5C30,10.034,23.732,5.333,16,5.333z';
this.icon_ = this.icons_[opts.icon];
this.setMap(opts.map);
}
MapCustomMarker.prototype = new google.maps.OverlayView();
MapCustomMarker.prototype.onAdd = function() {
// Create the DIV and set some basic attributes.
var div = document.createElement('div');
div.style.border = "none";
div.style.borderWidth = "0px";
div.style.position = "absolute";
div.style.cursor = "pointer";
div.style.width = this.width_+"px";
div.style.height = this.height_+"px";
var paper = Raphael(div,this.height_, this.width_);
var el = paper.path(Raphael.transformPath(this.icon_, 's'+this.scale_)).attr({fill: this.color_, stroke: "#333333"});
// 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 overlayImage pane.
var panes = this.getPanes();
panes.overlayMouseTarget.appendChild(div);
}
MapCustomMarker.prototype.draw = function() {
// Size and position the overlay.
var overlayProjection = this.getProjection();
// We'll use these coordinates to position the DIV.
var o = overlayProjection.fromLatLngToDivPixel(this.pos_);
var l = o.x - Math.round(this.width_ / 2);
var t = o.y - this.height_;
this.div_.style.left = l + 'px';
this.div_.style.top = t + 'px';
}
MapCustomMarker.prototype.onRemove = function() {
this.div_.parentNode.removeChild(this.div_);
this.div_ = null;
}
MapCustomMarker.prototype.hide = function() {
console.log(this.div_);
console.log(this.color_);
if (this.div_) {
this.div_.style.visibility = "hidden";
}
}
MapCustomMarker.prototype.show = function() {
if (this.div_) {
this.div_.style.visibility = "visible";
}
}
MapCustomMarker.prototype.toggle = function() {
if (this.div_) {
if (this.div_.style.visibility == "hidden") {
this.show();
} else {
this.hide();
}
}
}
This class creates markers on my map with the Raphael icons very nicely.
The problem comes when I want to hide or show any specific marker.
var marker = new MapCustomMarker({position: pos, map: self.map, icon:'help', color:'#e32636'});
marker.hide();
marker.hide() is not hiding the markers.
You'll notice in the "hide" method, I have two console.log commands testing the values of this.color_ and this.div_. console.log(this.color_) returns the color set when the object is initiated. console.log(this.div_) returns null even though it was obviously altered in the 'onAdd' and 'draw' methods when the marker was created.
I'm not sure if this is a misunderstanding of public and private properties in javascript or something else. I used the google maps custom overlay example almost exactly.
If anyone has any ideas, please pass them along. (And aside from this one issue, I hope this code will assist others who want to merge Raphael JS capabilities with Google Maps.)
Thanks!
So it appears that marker.hide() is being called before the methods 'onAdd' and 'draw' have a chance to alter the this.div_ variable when the object is instantiated. Since I want all markers to be hidden when they are created, I'm just going to add
div.style.visibility = "hidden";
to the onAdd method, and will call maker.show() later, well after all of the markers have been loaded.

Adding child divs dynamically to a parent div doesn't make the parent div grow to accommodate the child divs

I have a div on the main page:
<div id="Alerts" class="Alerts"><a class="handle" href=""></a></div>
I'm populating this div with others div at run time:
function CreateDivIncident(errorcode, name, address, lat, lng) {
var div = CreateDefaultDiv('Alerts');
var html = errorcode + '</b> Name:' + name + ' Address: ' + address;
div.innerHTML = html;
google.maps.event.addDomListener(div, 'mouseover', function () { div.style.backgroundColor = '#55FFFF'; });
google.maps.event.addDomListener(div, 'mouseout', function () { div.style.backgroundColor = 'white'; });
google.maps.event.addDomListener(div, 'mouseup', function () { gmap.panTo(new google.maps.LatLng(lat, lng)); });
}
function CreateDefaultDiv(parent) {
var div = document.createElement('div');
div.style.marginBottom = '5px';
div.style.backgroundColor = 'white';
div.style.border = 'solid 1px';
div.style.fontSize = "16px";
div.style.fontFamily = "Arial";
div.style.paddingRight = "5px";
document.getElementById(parent).appendChild(div);
return div;
}
The new divs are showing and acting to clicks well but the parent div isn't growing its height correspondingly. The new divs are just "floating" above it.
What am I missing here? Any advice will be welcome.
Write float:left css rule on .Alerts or #Alerts. Parent container will take the height and width. By using border:1px solid red; on your parent div and child divs you do testing, i mean which element is outside and which one is inside. By identifying the boundaries.
Update: Remove the height 110px;

Categories

Resources