Search code examples
javascriptopenlayers

Can I replace the OpenLayers editing toolbar with normal buttons?


This little OpenLayers.Control.EditingToolbar from is inserted by default:

It's not really evident what these buttons mean. I would like to replace this editing toolbar with a button group (e.g. like the one Twitter Bootstrap offers):

The markup of the editing toolbar currently is this:

<div id="panel" class="olControlEditingToolbar">
  <div class="olControlNavigationItemInactive olButton"></div>
  <div class="olControlDrawFeaturePointItemActive olButton"></div>
  <div class="olControlDrawFeaturePathItemInactive olButton"></div>
  <div class="olControlDrawFeaturePolygonItemInactive olButton"></div>
</div>

The images are basic sprites – so I know I could change these. But I can't see how I could get away from these divs, replacing them with buttons. I thought about just creating the button group manually and add click() event listeners to the buttons, triggering OpenLayers' different editing modes. But I couldn't find any documentation on how I could do that.


So, basically, I see these options:

  • Create button group manually, and trigger the appropriate OpenLayers events through my own JS — but which events do I need to trigger?

  • Don't use the EditingToolbar, but manually build my toolbar with OpenLayers — how could I do that?

  • Modify the automatically created editing toolbar by hacking the OpenLayers source (meh…) — is this worth the effort?


Solution

  • The best way is to manually build the control buttons. Based on the Draw Feature Example, you can go ahead and add your controls:

    drawControls = {
      point: new OpenLayers.Control.DrawFeature(pointLayer,
          OpenLayers.Handler.Point),
      line: new OpenLayers.Control.DrawFeature(lineLayer,
          OpenLayers.Handler.Path),
      polygon: new OpenLayers.Control.DrawFeature(polygonLayer,
          OpenLayers.Handler.Polygon),
      )
    };
    
    for(var key in drawControls) {
      map.addControl(drawControls[key]);
    }
    

    Then, add a function that changes the currently used control based on a clicked element:

    function toggleControl(element) {
        for(key in drawControls) {
            var control = drawControls[key];
            if(element.value == key && element.checked) {
                control.activate();
            } else {
                control.deactivate();
            }
        }
    }
    

    Finally, create the HTML markup yourself. For each element that changes the control, add an onClick handler that calls the toggleControl function. You can also attach the click handler through jQuery, but in essence, this works:

    <ul id="controlToggle">
      <li>
          <input type="radio" name="type" value="none" id="noneToggle"
                 onclick="toggleControl(this);" checked="checked" />
          <label for="noneToggle">navigate</label>
      </li>
      <li>
          <input type="radio" name="type" value="point" id="pointToggle" onclick="toggleControl(this);" />
          <label for="pointToggle">draw point</label>
      </li>
      <!-- add more elements here, based on which draw modes you added -->
    </ul>
    

    You can see this in action here (sign up with a test user, no real e-mail needed) and find the code on GitHub.