Specifically, I'm trying to make a drop down menu filled with links that will direct to the specified locations in google maps when clicked. I managed to get google maps embedded into my page, but for some reason I cannot seem to get the drop down to occur and cannot find the problem in my code. I also am struggling to understand how to actually create the links in the dropdown menu to direct to the selected location on the google map. Any help would be appreciated. The code I have so far...
function myFunction() {
document.getElementById("myDropdown").classList.toggle("show");
}
window.onclick = function(event) {
if (!event.target.matches('.dropbtn')) {
var dropdowns = document.getElementByClassName("dropdown-content");
var i;
for (i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('show')) {
openDropdown.classList.remove('show')
}
}
}
}
function initMap() {
var Columbia = {
lat: 34.006140,
lng: -81.037532
};
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 4,
center: Columbia
});
var marker = new google.maps.Marker({
position: Columbia,
map: map
});
}
.dropbtn {
background-color: #4caf50;
color: white;
padding: 16px;
font-size: 16px;
border: none;
cursor: pointer;
}
.dropbtn:hover,
.dropbtn:focus {
background-color: #3e8e41;
}
.dropdown {
position: relative;
display: inline-block;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
overflow: auto;
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
z-index: 1;
}
.dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
.dropdown a:hover {
background-color: #f1f1f1
}
#map {
height: 400px;
width: 100%;
}
<script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB5cD8oVYji2MWCAj8JzrAzQtpBy12W30o&callback=initMap">
</script>
<h3>Google Maps/Form Assignment</h3>
<div id="map"></div>
<div class="dropdown">
<button onclick="myFunction()" class="dropbtn">Select a location</button>
<div id="myDropdown" class="dropdown-content">
London, England
Tokyo, Japan
New York City, USA
</div>
</div>
I see you have added 2 different functions for the same process, you only need 1 so i will show the code with the fixes:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
.dropbtn {
background-color: #4caf50;
color: white;
padding: 16px;
font-size: 16px;
border: none;
cursor: pointer;
}
.dropbtn:hover, .dropbtn:focus{
background-color: #3e8e41;
}
.dropdown{
position: relative;
display: inline-block;
}
.dropdown-content{
display: none;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
overflow: auto;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
}
/*Add this rule so the dropdown can be shown*/
.dropdown-content.show{
display: block;
}
.dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
.dropdown a:hover {
background-color: #f1f1f1
}
#map {
height: 400px;
width: 100%;
}
</style>
</head>
<body>
<h3>Google Maps/Form Assignment</h3>
<div id="map"></div>
<div class="dropdown">
<button class="dropbtn">Select a location</button>
<div id="myDropdown" class="dropdown-content">
London, England
Tokyo, Japan
New York City, USA
</div>
</div>
<script>
window.onclick = function(event){
var target = event.target;
if(target.matches('.dropbtn')){
var dropdowns = document.getElementsByClassName("dropdown-content"); //This returns a HTMLCollection
for(i=0; i < dropdowns.length; i++){
// Since dropdowns is a HTMLCollection, extract the node from the collection
var dropdown = dropdowns.item(i);
// Toggle the dropdown whenever the button is clicked
dropdown.classList.toggle("show");
}
}
if(target.matches(".dropdown-content > a")){
// Get the location name from the hash
var location = target.hash.slice(1);
// Extract the location map and set it as center
map.setCenter(positions[location]);
}
};
</script>
<script>
function initMap() {
// Set all locations map
window.positions = {
london: {
lat: 51.5013616,
lng: -0.1965444
},
southCarolina: {
lat: 34.006140,
lng: -81.037532
}
};
window.map = new google.maps.Map(document.getElementById('map'), {
zoom: 4,
center: positions.southCarolina
});
// Add marker positions in the map
var markers = {
london: new google.maps.Marker({
position: positions.london,
map: map
}),
southCarolina: new google.maps.Marker({
position: positions.southCarolina,
map: map
})
};
}
</script>
<script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB5cD8oVYji2MWCAj8JzrAzQtpBy12W30o&callback=initMap">
</script>
</body>
</html>
i have added in the comments what should have been done as difference from your code.
You need to know that document.getElementsByClassName returns a HTMLCollection object which only has length as property and 2 methods which are item and namedItem, you can see the docs for HTMLCollection and docs for getElementsByClassName
EDIT: I have also added a section code for handling the map position view when a dropdown item is clicked, note i just added an example for london so you could continue doing the rest for other locations
Related
Google Maps Traffic Widget
i want to show the widget from the picture above in my embedded map to show typical traffic. but i can't seem to find any documentation for this. this is my current javascript code
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 17,
clickableIcons: false,
center: {lat: 34.04924594193164, lng: -118.24104309082031}
});
var myMarker = new google.maps.Marker({
position: {lat: 34.04924594193164, lng: -118.24104309082031},
map: map,
title: 'myMarker',
draggable: false
});
var trafficLayer = new google.maps.TrafficLayer();
trafficLayer.setMap(map);
}
Exactly what you want is not provided in official document.
You can create custom legends base on this tutorial
function initMap() {
var options = {
zoom: 13,
center: {lat: 34.04924594193164, lng: -118.24104309082031},
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById('map-container'), options);
//var trafficLayer = new google.maps.TrafficLayer();
//trafficLayer.setMap(map);
var controlDiv = document.createElement('DIV');
$(controlDiv).addClass('gmap-control-container')
.addClass('gmnoprint');
var controlUI = document.createElement('DIV');
$(controlUI).addClass('gmap-control');
$(controlUI).text('Traffic');
$(controlDiv).append(controlUI);
var legend = '<ul>'
+ '<li><span style="background-color: #30ac3e"> </span><span style="color: #30ac3e"> > 80 km per hour</span></li>'
+ '<li><span style="background-color: #ffcf00"> </span><span style="color: #ffcf00"> 40 - 80 km per hour</span></li>'
+ '<li><span style="background-color: #ff0000"> </span><span style="color: #ff0000"> < 40 km per hour</span></li>'
+ '<li><span style="background-color: #c0c0c0"> </span><span style="color: #c0c0c0"> No data available</span></li>'
+ '</ul>';
var controlLegend = document.createElement('DIV');
$(controlLegend).addClass('gmap-control-legend');
$(controlLegend).html(legend);
$(controlLegend).hide();
$(controlDiv).append(controlLegend);
// Set hover toggle event
$(controlUI)
.mouseenter(function() {
$(controlLegend).show();
})
.mouseleave(function() {
$(controlLegend).hide();
});
var trafficLayer = new google.maps.TrafficLayer();
google.maps.event.addDomListener(controlUI, 'click', function() {
if (typeof trafficLayer.getMap() == 'undefined' || trafficLayer.getMap() === null) {
$(controlUI).addClass('gmap-control-active');
trafficLayer.setMap(map);
} else {
trafficLayer.setMap(null);
$(controlUI).removeClass('gmap-control-active');
}
});
map.controls[google.maps.ControlPosition.TOP_RIGHT].push(controlDiv);
}
/* Always set the map height explicitly to define the size of the div
* element that contains the map. */
#map-container {
height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html, body {
height: 100%;
margin: 0;
padding: 0;
}
.gmap-control-container {
margin: 5px;
}
.gmap-control {
cursor: pointer;
background-color: -moz-linear-gradient(center top , #FEFEFE, #F3F3F3);
background-color: #FEFEFE;
border: 1px solid #A9BBDF;
border-radius: 2px;
padding: 0 6px;
line-height: 160%;
font-size: 12px;
font-family: Arial,sans-serif;
box-shadow: 2px 2px 3px rgba(0, 0, 0, 0.35);
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-o-user-select: none;
user-select: none;
}
.gmap-control:hover {
border: 1px solid #678AC7;
}
.gmap-control-active {
background-color: -moz-linear-gradient(center top , #6D8ACC, #7B98D9);
background-color: #6D8ACC;
color: #fff;
font-weight: bold;
border: 1px solid #678AC7;
}
.gmap-control-legend {
position: absolute;
text-align: left;
z-index: -1;
top: 20px;
right: 0;
width: 150px;
height: 66px;
font-size: 10px;
background: #FEFEFE;
border: 1px solid #A9BBDF;
padding: 10px;
box-shadow: 2px 2px 3px rgba(0, 0, 0, 0.35);
}
.gmap-control-legend ul {
margin: 0;
padding: 0;
list-style-type: none;
}
.gmap-control-legend li {
line-height: 160%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="map-container"></div>
<!-- Replace the value of the key parameter with your own API key. -->
<script async defer
src="https://maps.googleapis.com/maps/api/js?callback=initMap">
</script>
I would like to modify my google map in the following way:
so I would like to have 2 (or more) couples of buttons (with custom icon) on the bottom left of the map BUT on the top of the standard buttons of google that is streetview and zoom..
Do you think is possible?
So far i was only able to move my custom buttom on the BOTTOM_LEFT, BOTTOM_RIGHT, BOTTOM and so on..
Also as you can see I would like to have a VERTICAL Drawing Manager and not a horizontal one.
This is what I did: example
In particular when I do this
map.controls[google.maps.ControlPosition.BOTTOM].push(customControlDiv);
i would like to add instead some coordinate or pixel positions..
You can't define coordinates or pixel positions, but you may control the position via CSS.
e.g. for controls placed at the BOTTOM use margin-bottom to move them upwards from the position that has been set by the API
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 12,
center: {
lat: 0,
lng: 0
},
noClear: true,
disableDefaultUI:true
});
map.controls[google.maps.ControlPosition.RIGHT_BOTTOM].push(document.getElementById('ctrl1'));
map.controls[google.maps.ControlPosition.RIGHT_BOTTOM].push(document.getElementById('ctrl2'));
}
html,
body,
#map {
height: 100%;
margin: 0;
padding: 0;
}
#ctrls {
display: none;
}
#ctrl1 {
margin: 10px;
margin-bottom: 20px;
background: red;
}
#ctrl1::before {
content: '#ctrl1';
display: block;
}
#ctrl2 {
margin: 10px;
margin-bottom: 5px;
background: yellow;
}
#ctrl2::before {
content: '#ctrl2';
display: block;
}
.ctrl {
border: 1px solid #818181;
border-radius: 5px;
}
.ctrl strong{
border: 1px solid #818181;
border-radius: 3px;
background:#fff;
display:block;
}
<div id="map">
<div id="ctrls">
<div id="ctrl1" class="ctrl">
<strong>Button 1-1</strong>
<strong>Button 1-2</strong>
</div>
<div id="ctrl2" class="ctrl">
<strong>Button 2-1</strong>
<strong>Button 2-2</strong>
</div>
</div>
</div>
<script async defer src="https://maps.googleapis.com/maps/api/js?callback=initMap"></script>
Google Maps doesn't show in a nav-tab.
It doesn't show the place, but when I click on the map; it's correct in google.
the problem
HTML:
<div class="tab-content">
<div role="tabpanel" class="tab-pane fade" id="locatie"><?php if ($object->hasLocation): ?>
<div>
<h2>Kaart</h2>
<div id="google-map"></div>
<h2>Street View</h2>
<div id="google-streetview"></div>
</div>
<?php endif; ?></div>
</div>
JS
(function($, exports) {
'use strict';
var GoogleMap = exports.GoogleMap = function(options) {
this.map = null;
this.markers = [];
this.bounds = null;
this.info = null;
this.options = $.extend({
container: '#google-map',
mapContainer: null,
map: {}
}, options || {});
this.$container = null;
};
CSS
.single-post-tst {
.entry-content {
width: 100%;
margin: 2% 0 10%;
display: inline-block;
p {
font-size: 16px;
}
}
.container-content-single {
ul, ol {
margin: 0 0 1.5em 0;
}
.nav-tabs {
border: 1px solid #ddd;
li {
margin-bottom: 0;
border-right: 1px solid #ddd;
}
li:last-child {
border-right: none;
}
li a {
border-radius: 0;
line-height: 2em;
margin-right: 0;
}
li a:hover {
background-color: #F29902;
color: #fff;
}
li.active > a {
padding-bottom: 12px;
}
a.nav-link.active {
background-color: #F29902;
color: #fff;
}
}
.nav-tabs>li.active>a, .nav-tabs>li.active>a:focus, .nav-tabs>li.active>a:hover {
border: none;
background-color: #F29902;
color: #fff;
}
}
}
#google-map,
#google-streetview {width:100%; height:500px;}
I think the problem is with this line in JS:
container: '#google-map',
When I put the map out off the tab, it works correct.
But I can't find any solution to show the map correct in the tab.
It shows now but not full width, I add this to CSS:
.tab-content.tab-pane,
.tab-pane {
/* display: none; */
display: block;
visibility: hidden;
position: absolute;
}
.tab-content.active,
.tab-content .tab-pane.active,
.tab-pane.active {
/* display: block; */
visibility: visible;
position: static;
}
It look like this now
When I say width: 100%; it doesn't make full width
If the map is on a secondary tab it wont get the proper sizing, if you can place him on the active tab the problem will be solved.
If you want to maintain the map on an hidden tab, please check how to force the refresh / resize of the map when it becomes visible.
How do I resize a Google Map with JavaScript after it has loaded?
Sample code:
google.maps.event.trigger(map, "resize");
EDIT, another option:
You can also set a fixed size for the map, you can check the code sample here ;)
how to deal with google map inside of a hidden div (Updated picture)
I found a solution:
.tab-content > .tab-pane {
display: block;
height:0;
overflow:hidden;
}
.tab-content > .active {
display: block;
height:auto;
}
So on my site I'm using Google Maps + Streetview:
https://developers.google.com/maps/documentation/javascript/examples/streetview-simple
Also I'm using standard searchbox with autocomplete, the problem is when I enter some locations, there is no streetview, just Photo Sphere image without any controls for moving around like in standard streetview...
I really don't want Photo Sphere, because I want my users to freely move around with street view, and now they sometimes get "trapped" in one Photo Sphere image... Is there a way I can force streetview without Photo Sphere?
I'm not sure how to turn off PhotoSpheres, but I did find a workaround that may be useful to you. I noticed at https://developers.google.com/maps/documentation/javascript/reference#StreetViewSource that when searching for a location, if you set the source to OUTDOOR, then PhotoSpheres are not returned.
Therefore, if you add listeners for location changes, and then search for the location without PhotoSpheres, I think you should be able to prevent them from showing up.
Here is a modified google maps example to illustrate:
<!DOCTYPE html>
<html>
<head>
<title>Place Autocomplete without PhotoSpheres</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<style>
html, body {
height: 100%;
margin: 0;
padding: 0;
}
#map, #pano {
height: 100%;
width: 50%;
float:left;
}
.controls {
margin-top: 10px;
border: 1px solid transparent;
border-radius: 2px 0 0 2px;
box-sizing: border-box;
-moz-box-sizing: border-box;
height: 32px;
outline: none;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
}
#pac-input {
background-color: #fff;
font-family: Roboto;
font-size: 15px;
font-weight: 300;
margin-left: 12px;
padding: 0 11px 0 13px;
text-overflow: ellipsis;
width: 300px;
}
#pac-input:focus {
border-color: #4d90fe;
}
.pac-container {
font-family: Roboto;
}
#type-selector {
color: #fff;
background-color: #4d90fe;
padding: 5px 11px 0px 11px;
}
#type-selector label {
font-family: Roboto;
font-size: 13px;
font-weight: 300;
}
</style>
</head>
<body>
<input id="pac-input" class="controls" type="text"
placeholder="Enter a location">
<div id="map"></div>
<div id="pano"></div>
<script>
var map;
var panorama;
var streetViewService;
var DEFAULT_PROXIMITY = 50;
var MAX_PROXIMITY = 10000;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: -33.8688, lng: 151.2195},
zoom: 13
});
var input = /** #type {!HTMLInputElement} */(
document.getElementById('pac-input'));
map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);
var autocomplete = new google.maps.places.Autocomplete(input);
//autocomplete.bindTo('bounds', map);
streetViewService = new google.maps.StreetViewService();
panorama = new google.maps.StreetViewPanorama(
document.getElementById('pano'), {
position: {lat: -33.8688, lng: 151.2195},
pov: {
heading: 34,
pitch: 10
}
});
map.setStreetView(panorama);
autocomplete.addListener('place_changed', function() {
var place = autocomplete.getPlace();
if (!place.geometry) {
window.alert("Autocomplete's returned place contains no geometry");
return;
}
// If the place has a geometry, then present it on a map.
if (place.geometry.location) {
findClosestStreetView(place.geometry.location, DEFAULT_PROXIMITY);
}
});
function findClosestStreetView(point, proximity) {
streetViewService.getPanorama({location: point, radius: proximity, source: google.maps.StreetViewSource.OUTDOOR}, function processSVData(data, status) {
if (status == google.maps.StreetViewStatus.OK) {
map.panTo(data.location.latLng);
panorama.setPano(data.location.pano);
} else {
if (proximity < MAX_PROXIMITY) {
findClosestStreetView(point, proximity + 50);
} else {
// NO PANARAMA FOUND - do something else here...
panorama.setVisible(false);
}
}
});
}
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?&libraries=places&callback=initMap" async defer></script>
</body>
</html>
sorry, I am very new to this. I want something similar to this here CartoDB multiple layer toggle,
only that I am not adding a SQL queried layer, but one from an URL. Each button should make one layer active, one layer at a time and always only one layer visible.
Thanks for any hint!
Best, Wolfram
<html>
<head>
<link rel="stylesheet" href="http://libs.cartocdn.com/cartodb.js/v3/themes/css/cartodb.css" />
<script src="http://libs.cartocdn.com/cartodb.js/v3/cartodb.js"></script>
<!--[if lte IE 8]>
<link rel="stylesheet" href="http://libs.cartocdn.com/cartodb.js/v2/themes/css/cartodb.ie.css" />
<![endif]-->
<style>
html, body {width:100%; height:100%; padding: 0; margin: 0;}
#cartodb-map { width: 100%; height:100%; background: black;}
#menu { position: absolute; top: 5px; right: 10px; width: 400px; height:60px; background: transparent; z-index:10;}
#menu a {
margin: 15px 10px 0 0;
float: right;
vertical-align: baseline;
width: 100px;
padding: 10px;
text-align: center;
font: bold 11px "Helvetica",Arial;
line-height: normal;
color: #555;
border-radius: 4px;
border: 1px solid #777777;
background: #ffffff;
text-decoration: none;
cursor: pointer;
}
#menu a.selected,
#menu a:hover {
color: #F84F40;
}
</style>
<script>
var map;
function init(){
// initiate leaflet map
map = new L.Map('cartodb-map', {
center: [-22.8,-43.15],
zoom: 10
})
L.tileLayer('https://stamen-tiles-{s}.a.ssl.fastly.net/toner-lite/{z}/{x}/{y}.png', {
attribution: ' '
}).addTo(map);
}
var layerUrl1 = 'https://riomapia.cartodb.com/api/v2/viz/d79239a6-51af-11e5-ba37-0e853d047bba/viz.json';
var layerUrl2 = 'https://riomapia.cartodb.com/api/v2/viz/633f93e0-51b0-11e5-b512-0e4fddd5de28/viz.json';
var layerUrl3 = 'https://riomapia.cartodb.com/api/v2/viz/4fa846f0-51b1-11e5-bd3c-0e853d047bba/viz.json';
function showLayer(layerToShow) {
//turn off all layers
layer.forEach(function(i) {
i.hide()
});
switch (layerToShow.id) {
case "Renda1":
layer.show(layerUrl1);
break;
case "Renda2":
layer.show(layerUrl2);
break;
case "Renda3":
layer.show(layerUrl3);
break;
}
return true;
}
</script>
</head>
<body onload="init()">
<div id='cartodb-map'></div>
<div id='menu'>
Renda domiciliar por pessoa
Pessoas < R$ 140
Pessoas < R$ 70
</div>
</body>
</html>
I'm not sure that you can do this (but I'm not certain) - however, I looked at the json files that you are linking to, and I see that the data is from Open Street Map. Have you tried looking at this tutorial?
http://docs.cartodb.com/tutorials/osm.html
Maybe that will help?