Keyboard accessible Google map

The basic zoom and pan controls on embedded Google maps are not keyboard accessible.

This can be addressed by including the map via one of the scripts in the examples below. Try it out by pressing the Tab key to move focus to the map controls. Once a map control has focus it can be activated using the Enter key.

To pan the map, move focus to one of the zoom controls, then press an Arrow key on the keyboard.

Example 1 - default controls

Code

<!DOCTYPE html>
<html lang="en">
<head>
    
<meta charset="utf-8">
    
<title>Keyboard access to Google maps</title>
<style>

#map_canvas {
     width
: 500px;
     height
: 400px;
}
</style>
<!--add Google map library-->
<script src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>

<!--add keybpard access script-->
<script>
(function(){

if(!window.visionaustralia) window.visionaustralia = {};

visionaustralia
.addmap = function(domid,lat,lon,zo){

    
var map;
    
function init() {
        
var map_canvas = document.getElementById(domid);
        
var map_options = {
            center
: new google.maps.LatLng(lat,lon),
            zoom
: zo,
            mapTypeId
: google.maps.MapTypeId.ROADMAP
        
}
        map
= new google.maps.Map(map_canvas, map_options);

        
var hPan = Math.floor(map_canvas.offsetHeight/3);
        
var wPan = Math.floor(map_canvas.offsetWidth/3);

        
var googListener = google.maps.event.addListener(map, 'tilesloaded', function() {

            
var titles = {"zoom in":1,"zoom out":1,"show street map":1,"show satellite imagery":1};
            
var divs = map_canvas.getElementsByTagName("div");
            
for(var i=0,el;el=divs[i];i++){

                
var title = el.getAttribute("title")
                
if(title) title=title.toLowerCase().trim();
                
if(title in titles){

                    el
.setAttribute("tabindex","0");
                    el
.setAttribute("role","button");
                    el
.setAttribute("aria-label",title);
                    el
.addEventListener("keydown", function(ev){
                        
var key = ev.keyCode || ev.which;
                        
if(key == 13 || key == 32){
                            
var event = document.createEvent('HTMLEvents');
                            event
.initEvent('click', true, false);
                            
this.dispatchEvent(event);

                        
}else if(key==40) {//down
                            map
.panBy(0, wPan);
                        
}else if(key==38) {//up
                            map
.panBy(0, -wPan);
                        
}else if(key==37) {//left
                            map
.panBy(-hPan, 0);
                        
}else if(key==39) {//right
                            map
.panBy(hPan, 0);
                        
}else{
                            
return
                        
}
                        ev
.preventDefault();
                    
});

                    
(function(el){
                        
var mo = false;
                        
var bo = el.style.border;
                        
var ma = el.style.margin;
                        
var bc = el.style.backgroundColor;
                        
var op = el.style.opacity;

                        el
.addEventListener("mouseover",(function(){mo=true;}));
                        el
.addEventListener("mouseout",(function(){mo=false;}));

                        el
.addEventListener("focus",(function(){
                            
if(mo)return;
                            el
.style.border ="2px solid blue";
                            el
.style.margin="-2px";
                            el
.style.backgroundColor = "transparent";
                            el
.style.opacity = "1";
                        
}));
                        el
.addEventListener("blur",(function(){
                            el
.style.border = bo;
                            el
.style.margin= ma;
                            el
.style.backgroundColor = bc;
                            el
.style.opacity = op;
                        
}));
                    
})(el);
                
}
            
}
            
            google
.maps.event.removeListener(googListener);
        
});
    
}//end init

    google
.maps.event.addDomListener(window, 'load', init);

}//end addmap
})();
</script>
</head>
<body>

<p>content....</p>
<div id="map_canvas"></div>
<p>.... other content</p>

<script>
//"map_canvas" is the id of the div that will contain the map and the 3 parameters after are: latitude, longitude and zoom level
visionaustralia
.addmap("map_canvas",45.6,4.9,8);
</script>

</body>
</html>

Example 2 - custom controls

This example replaces the default controls with a custom SVG control.

Press the Tab key to move focus to a control, then press the Enter key to activate it.

To pan the map, move focus to one of the zoom controls, then press an Arrow key on the keyboard.

Code

<!DOCTYPE html>
<html lang="en">
<head>
    
<meta charset="utf-8">
    
<title>Keyboard access to Google maps - custom controls</title>
<style>

#map_canvas_2 {
     width
: 500px;
     height
: 400px;
}
</style>
<!--add Google map library-->
<script src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>

<!--add keybpard access script-->
<script>
(function(){

if(!window.visionaustralia) window.visionaustralia = {};

visionaustralia
.addmapII = function(domid,lat,lon,zo){

    
var map;
    
    
function init() {
        
var map_canvas = document.getElementById(domid);
        
var map_options = {
            center
: new google.maps.LatLng(lat,lon),
            zoom
: zo,
            mapTypeId
: google.maps.MapTypeId.ROADMAP,
            disableDefaultUI
: true
        
}
        map
= new google.maps.Map(map_canvas, map_options);

        
var hPan = Math.floor(map_canvas.offsetHeight/3);
        
var wPan = Math.floor(map_canvas.offsetWidth/3);
        
        
var div = document.createElement("div");
        div
.setAttribute("style","position:absolute;border:none;outline:none;padding:0px;margin:0px 6px 0px 0px;");
        div
.innerHTML ='<svg height="60" width="60" viewBox="0,0,102,102" aria-hidden="true" focusable="false"><g class="yang" style="cursor:pointer"><circle cx="51" cy="51" r="50" fill="white" style="stroke-width:1px;stroke:black"/><circle cx="51" cy="76" r="12" fill="black"/><path d="M 44,74 h14 v4 h-14 z" fill="white"/></g><g class="yin" style="cursor:pointer"><path d="M 51,1 C 65,1 76,12 76,26 76,40 65,51 51,51 37,51 26,62 26,76 26,90 37,101 51,101 C 23,101 1,79 1,51 1,23 23,1 51,1" fill="black" stroke="black"/><circle cx="51" cy="26" r="12" fill="white" stroke="black"/><path d="M 43,24 h6 v-6 h4 v6 h6 v4 h-6 v6 h-4 v-6 h-6 z" fill="black"/></g></svg>';
        
        
var yin = div.getElementsByClassName("yin")[0];
        
var yang = div.getElementsByClassName("yang")[0];
        
        
var bStyl = "position: absolute !important;clip: rect(1px, 1px, 1px, 1px);padding: 0 !important;border: 0 !important;height: 1px !important;width: 1px !important;overflow: hidden";
        
        
var yinB = document.createElement("button");
        yinB
.setAttribute("aria-label","Zoom out");
        yinB
.setAttribute("style",bStyl);
        
        
var yangB = document.createElement("button");
        yangB
.setAttribute("aria-label","Zoom in");
        yangB
.setAttribute("style",bStyl);
        
        div
.appendChild(yinB);
        div
.appendChild(yangB);
    
        map
.controls[google.maps.ControlPosition.RIGHT_BOTTOM].push(div);

        
var arr,i,el;
        arr
= [yin,yinB];
        
for(i=0;el=arr[i];i++){
            el
.addEventListener('click', function(ev) {
                map
.setZoom(map.getZoom() + 1);
                ev
.stopPropagation();
                ev
.preventDefault();
            
});
        
}
        arr
= [yang,yangB];
        
for(i=0;el=arr[i];i++){
            el
.addEventListener('click', function(ev) {
                map
.setZoom(map.getZoom() - 1);
                ev
.stopPropagation();
                ev
.preventDefault();
            
});
        
}
        
        yinB
.addEventListener('focus', function() {
            
//IE wants this done everytime(?)
            
var yins = yin.getElementsByTagName("*");
            yins
[0].setAttribute("fill","yellow");
            yins
[0].setAttribute("stroke-width","1");
            yins
[1].setAttribute("stroke-width","1");
        
});
        yinB
.addEventListener('blur', function() {
            
var yins = yin.getElementsByTagName("*");
            yins
[0].setAttribute("fill","black");
            yins
[0].setAttribute("stroke-width","0");
            yins
[1].setAttribute("stroke-width","0");
        
});
        yangB
.addEventListener('focus', function() {
            
var yangs = yang.getElementsByTagName("*");
            yangs
[0].setAttribute("fill","yellow");
        
});
        yangB
.addEventListener('blur', function() {
            
var yangs = yang.getElementsByTagName("*");
            yangs
[0].setAttribute("fill","white");
        
});
        
        arr
= [yinB,yangB];
        
for(i=0;el=arr[i];i++){
            el
.addEventListener("keydown", function(ev){
                
var key = ev.keyCode || ev.which;
                
if(key==40) {//down
                    map
.panBy(0, wPan);
                
}else if(key==38){//up
                    map
.panBy(0, -wPan);
                
}else if(key==37){//left
                    map
.panBy(-hPan, 0);
                
}else if(key==39){//right
                    map
.panBy(hPan, 0);
                
}else if(key==61 || key== 107){
                     map
.setZoom(map.getZoom() + 1);
                
}else if(key==173 || key== 109){
                     map
.setZoom(map.getZoom() - 1);
                
}else{
                    
return;
                
}
                ev
.stopPropagation();
                ev
.preventDefault();
            
});
        
}
    
}//end init

    google
.maps.event.addDomListener(window, 'load', init);

}//end addmap
})();
</script>
</head>
<body>

<p>content....</p>
<div id="map_canvas_2"></div>
<p>.... other content</p>

<script>
//"map_canvas" is the id of the div that will contain the map and the 3 parameters after are: latitude, longitude and zoom level
visionaustralia
.addmapII("map_canvas_2",55.651,12.081,13);
</script>

</body>
</html>

Terms of Use

Developed by Pierre Frederiksen. Pierre is a Digital Access Specialist at Vision Australia

This software is being provided "as is", without any express or implied warranty. In particular, Vision Australia does not make any representation or warranty of any kind concerning the reliability, quality, or merchantability of this software or its fitness for any particular purpose. additionally, Vision Australia does not guarantee that use of this software will ensure the accessibility of your web content or that your web content will comply with any specific web accessibility standard.

Creative commons licence - logo
This work is licensed under a Creative Commons License








Print Print larger font