Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

EDIT: I have cross-posted this to Drupal Answers. I hope this isn't too much against the rules --- I think the answer will be something to do with both Drupal and OpenLayers. http://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.

EDIT: I've changed the code to show the Drupal-specific elements.

(function ($) {
  Drupal.behaviors.openlayers_switcher = {
    attach: function(context, settings) {
      $(document).ready(function() {
        $('[id^=openlayers-switcher-block--]').click(function(e) {
          $(this).toggleClass('active');
          // 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);
          // }
        });
      });
    }
  }
}(jQuery));

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

EDIT: So 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) {
  e.preventDefault();
  e.stopPropagation();

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

In any case, I'm new to openlayers and would be grateful for a way forward!

Thanks!

share|improve this question
    
In your site, I fail to get the DOM objects through '$' but can get them by using 'jQuery', so your jQuery might not be loaded correctly, or there might be other library using '$'. –  Mingfeng Nov 16 '12 at 13:49
    
Thank you for your response, I'm using standard drupal code to deal with the $ namespacing ... I have updated the original post. –  mcaleaa Nov 17 '12 at 13:31

3 Answers 3

Edit: My first answer was totally off base. This one should be more helpful.

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.

Hope that helps.

share|improve this answer
    
that's not it, sorry for not being clear: if I comment out the first line and uncomment the other lines and add alerts like this. // layers[0].setVisibility(true); // this doesn't work alert(layers[0].visibility); if (layers[0].visibility) { layers[0].setVisibility(false); } else { layers[0].setVisibility(true); } ... I get a first alert 'false' and a second 'true' –  mcaleaa Nov 17 '12 at 13:27
    
@MichaelLenahan Somehow I missed that those lines were commented out. I think I figured out your immediate problem, although i haven't figured out a solution. –  canisrufus Nov 17 '12 at 17:04
    
Wow. Thanks! What an amazing answer! I needed those tips on debugging in the browser, that's help me get a grip on the problem. I think the main thing now is to implement my js properly as described in sites/all/modules/openlayers/docs/BEHAVIORS.txt - in other words as ever I need to rtfm! Thanks again. I'll report back! –  mcaleaa Nov 19 '12 at 12:02
    
@mcaleaa I hope it helps. Sorry I couldn't actually fix it ;) –  canisrufus Nov 19 '12 at 20:40

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];
layer.setVisibility(true);

I hope this helps.

share|improve this answer
2  
(+1) I suspect the layer is trapped in a closure. –  CaptDragon Nov 16 '12 at 14:50
    
Thanks both. I have edited the code above to show the whole js that I am loading, including the drupal-specific parts (first/last 3 lines). I'm still not sure what's happening, not sure what 'the layer is trapped in a closure' means. When I find a way forward, I'll obviously come back here and post an update. Thanks again. –  mcaleaa Nov 17 '12 at 13:19
1  
@MichaelLenahan a closure is a data structure present in javascript that can cause headaches for the uninitiated. –  canisrufus Nov 17 '12 at 18:10
    
@canisrufus Great link about closures! –  dariapra Nov 17 '12 at 20:36

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.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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