Custom and accessible panel

http://openlayers.org/dev/examples/accessible-panel.html

by Mike Gifford

HTML

<script src="http://fbug.googlecode.com/svn/lite/branches/flexBox/content/firebug-lite-dev.js"></script>
<script src="http://openlayers.org/dev/OpenLayers.js"></script>
<link rel="stylesheet" href="http://openlayers.org/dev/examples/style.css">
<link rel="stylesheet" href="http://openlayers.org/dev/theme/default/style.css">
    <h1 id="title">Custom and accessible panel</h1>
    <div id="tags">
        panels, CSS, style, accessibility, button
    </div>
    <p id="shortdesc">
      Create a custom and accessible panel, styled entirely with
      CSS.
    </p>  
    <div id="panel"></div>
    <div id="map" class="smallmap"></div>

    <div id="docs">

      <p>An accessible panel:

      <ul>
      <li>The buttons are actual HTML buttons. You can therefore
      use the TAB key to give the focus to the panel's buttons, and the "ENTER"
      key to activate or trigger the corresponding control.</li>
      <li>The buttons include text and titles (displayed when a button
      is hovered).</li>
      <li>If you remove colors from the page (for example using FireFox's <a
          href="https://addons.mozilla.org/en-US/firefox/addon/no-color/">No
          Color extension</a>) the buttons are still visible, and
          accessible using the keyboard.</li>
      </ul>
      </p>

      <p>By default a panel creates buttons as divs. In this example the
      <code>createControlMarkup</code> panel function is overridden to create
      a more accessible markup for the buttons.  See the <a
          href="accessible-panel.js" target="_blank"> accessible-panel.js
          source</a> to see how this is done.</p>

      <p>Note: in IE 8, when a button is pressed its content shifts by 1 pixel.
      This is a <a
          href="http://labs.findsubstance.com/2009/05/21/ie8-form-button-with-background-image-on-click-css-bug/">known
          IE8 bug</a>, with known workarounds. No workaround is applied in this
      example though.</p>

    </div>

  <br />
  <p><a...

CSS

.olControlPanel button
{
  background-color:#FFF;
  border:1px solid;
  border-radius:4px;
  display:block;
  float:left;
  height:35px;
  margin:2px;
  overflow:visible;
  padding:0 5px;
  position:relative;
}

.olControlPanel button span
{
  padding-left:25px;
}

.olControlPanel button span:first-child
{
  display:block;
  left:2px;
  padding-left:0;
  position:absolute;
}

.olControlPanel .olControlDrawFeatureItemActive span:first-child
{
  background-image:url(http://openlayers.org/dev/theme/default/img/draw_line_on.png);
  height:22px;
  top:5px;
  width:24px;
}

.olControlPanel .olControlDrawFeatureItemInactive span:first-child
{
  background-image:url(http://openlayers.org/dev/theme/default/img/draw_line_off.png);
  height:22px;
  top:5px;
  width:24px;
}

.olControlPanel .olControlZoomBoxItemInactive span:first-child
{
  background-image:url(http://openlayers.org/dev/img/drag-rectangle-off.png);
  height:29px;
  top:2px;
  width:29px;
}

.olControlPanel .olControlZoomBoxItemActive span:first-child
{
  background-image:url(http://openlayers.org/dev/img/drag-rectangle-on.png);
  height:29px;
  top:2px;
  width:29px;
}

.olControlPanel .olControlZoomToMaxExtentItemInactive span:first-child
{
  background-image:url(http://openlayers.org/dev/img/zoom-world-mini.png);
  height:18px;
  top:8px;
  width:18px;
}

.olControlPanel .navHistory span:first-child
{
  background-image:url(http://openlayers.org/dev/theme/default/img/navigation_history.png);
  height:24px;
  top:4px;
  width:24px;
}

.olControlPanel .navHistoryPreviousItemActive span:first-child
{
  background-position:0 0;
}

.olControlPanel .navHistoryPreviousItemInactive span:first-child
{
  background-position:0 -24px;
}

.olControlPanel .navHistoryNextItemActive span:first-child
{
  background-position:-24px 0;
}

.olControlPanel .navHistoryNextItemInactive span:first-child
{
  background-position:-24px -24px;
}

JavaScript

(function($) {

var lon = 5;
var lat = 40;
var zoom = 5;
var map, layer;

function init() {
    map = new OpenLayers.Map( 'map', { controls: [] } );
    layer = new OpenLayers.Layer.WMS( 'OpenLayers WMS',
            'http://vmap0.tiles.osgeo.org/wms/vmap0', {layers: 'basic'} );
    map.addLayer(layer);

    vlayer = new OpenLayers.Layer.Vector( 'Editable' );
    map.addLayer(vlayer);
    
    zb = new OpenLayers.Control.ZoomBox({
        title: 'Zoom box: zoom clicking and dragging',
        text: 'Zoom'
    });

    var panel = new OpenLayers.Control.Panel({
        defaultControl: zb,
        createControlMarkup: function(control) {
            var button = document.createElement('button'),
                iconSpan = document.createElement('span'),
                textSpan = document.createElement('span');
            iconSpan.innerHTML = '&nbsp;';
            button.appendChild(iconSpan);
            if (control.text) {
                textSpan.innerHTML = control.text;
            }
            button.appendChild(textSpan);
            return button;
        }
    });

    panel.addControls([
        zb,
        new OpenLayers.Control.DrawFeature(vlayer, OpenLayers.Handler.Path,
            {title:'Draw a feature', text: 'Draw'}),
        new OpenLayers.Control.ZoomToMaxExtent({
            title:'Zoom to the max extent',
            text: 'World'
        })
    ]);
    
    nav = new OpenLayers.Control.NavigationHistory({
        previousOptions: {
            title: 'Go to previous map position',
            text: 'Prev'
        },
        nextOptions: {
            title: 'Go to next map position',
            text: 'Next'
        },
        displayClass: 'navHistory'
    });
    // parent control must be added to the map
    map.addControl(nav);
    panel.addControls([nav.next, nav.previous]);
    
    map.addControl(panel);

    map.setCenter(new OpenLayers.LonLat(lon, lat), zoom);
}

        
    init();
})(jQuery);