I have cross-posted this to Drupal Answers. I think the answer will be something to do with both Drupal and OpenLayers. https://drupal.stackexchange.com/questions/50733/openlayers-toggle-visibility-of-layer

I'm using OpenLayers in Drupal and am stuck while trying to make a layer toggle on and off (as it does from the right-side layer switcher).

See this map. http://dev.lambeth.coop/map

Click on food growing projects.

The code shows the Drupal-specific elements.

(function ($) {
  Drupal.behaviors.openlayers_switcher = {
    attach: function(context, settings) {
      $(document).ready(function() {
        $('[id^=openlayers-switcher-block--]').click(function(e) {
          // 27 is the length of 'openlayers-switcher-block--'
          // layername is the string following that.
          var layername = e.target.id.substring(27);
          var ol = $('.openlayers-map').data('openlayers');
          var layers = ol.openlayers.getLayersByName(layername);
          // this doesn't work
          // if (layers[0].visibility) {
            // layers[0].setVisibility(false);
          // }
          // else {
            // layers[0].setVisibility(true);
          // }

When I try to toggle visibility - the visibility doesn't change.

It appears that the entire click function is being called twice.

I've tried putting these lines (in various combinations) at the beginning of the function, as these have been suggested in google searches for 'click events firing twice' etc.

$('[id^=openlayers-switcher-block--]').click(function(e) {

... but these don't help - I still get the function called twice.


3 Answers 3


I cannot fully understand the code you have posted.

When using the library OpenLayers, the usual programming pattern - as seen in the examples available at OpenLayers web page - consists on creating an instance of OpenLayers.Map that is stored in a global variable, so it is available to every function.

Let us suppose that this variable is named map; then, you would get the layer whose visibility you want to toggle with a JavaScript code like this:

var layerName = 'food-growing-projects';
var layer = map.getLayersByName(layerName)[0];

The short version: You're correct that the onclick function is being called twice. The reason this is happening is that you're calling drupal.attachBehaviors() too many times - once in the drupal code, once in openlayers.js, and then once in openlayers_behavior_popup.js. If you remove it, though, other stuff breaks. You might try using the "once" command instead of "click", or finding a way to structure your application that it doesn't need to get called so much.

The longer version: This is how I figured out the onclick function is being called twice, and what was making it happen. This kind of turned into a tutorial on how to use a debugger, but I think that's important for us GIS devs to learn about somewhere. (There's something far more in depth here.)

I figured out that the onclick function is being called twice by setting a breakpoint in the onclick function. I then saw this breakpoint get triggered twice every time I clicked the button to toggle visibility.

Using Chrome, this is what I did:

  1. hit 'f12',
  2. click on 'Sources'
  3. in the file menu on the left side, locate and double click on openlayers_switcher.js
  4. This should open the file. In the left side of this, there are line numbers. Click on 9 (var layername = e.target.id.substring(27);). It should create a blue box over the number 9.

Next click the layer switcher. The blue box should get a red arrow. The script execution is paused on this line - you can look at variable values, and even modify the function (add in alert('hello, world!'); and hit ctrl+s if you want to try it). enter image description here

Then, if you hit f8, execution resumes... but you end up at the breakpoint again, because the onclick event gets called twice.

That answers what, but doesn't get to why. To do that, we need to find what is calling the click function.

To do that, we need to

  1. set a breakpoint on the click function (line 5),
  2. reload the page, and
  3. investigate the call stack.

The debugger should break on line 5. On the right side of the developer tools bar (aka the debugger), there should be a section called "Call Stack". Expand it if you need to.

enter image description here

The call stack lists the functions that you're inside of (this is where the phrase stack overflow comes from, incidentally: if you have too many functions on your call stack, the computer can run out of memory and have Bad Things happen). The top one is the context that you're currently in: Drupal.behaviors.openlayers_switcher. If you scroll down a little bit, there's one called Drupal.Attach behaviors. This one looks very promising: we're using drupal, we are working with behaviors, and are currently experiencing issues with the behavior being "attached" one too many times. Let's click on it and check it out.

When we do, go to this function:

Drupal.attachBehaviors = function (context, settings) {
  context = context || document;
  settings = settings || Drupal.settings;
  // Execute all of them.
  $.each(Drupal.behaviors, function () {
    if ($.isFunction(this.attach)) {
      this.attach(context, settings);

Cool. We see that this function, attachBehaviors, is using jquery to run "this.attach" on each item in Drupal.behaviors. This sounds suspiciously like where the problem is coming from, but this is the function definition, not where it's being called from. To find where it's being called from, we have to do a text search.

In the Chrome Developer Tools, hit "ctrl+shift+f". This brings up a small text box; search for "Drupal.AttachBehaviors". You'll find 8 references in 3 files, 3 of which are the function being invoked. Try taking the one from openlayers_behavior_popup.js out, and fixing the code in your layer toggler: it works! unfortunately, this breaks your application in some not-very-subtle ways.


I activated the layer by javascript and worked to version 2.10. See my code:

layer.setVisibility (true);

It worked the same way as if I had clicked.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.