I have an issue with filtering an Openlayers Map view with views exposed filters with AJAX enabled.

I had this working perfectly with an old version of Openlayers (beta 1), and recently I took the plunge and upgraded to beta5 which broke this ajax functionality (note filtering still works perfectly with AJAX disabled on the view). The problem with the ajax response is that it appeared that all openlayers js settings were being merged rather than overwritten. This meant that everything turned into an array and I was getting the JS error:

TypeError: Object [object Array] has no method 'toUpperCase' openlayers.js:445

I then updated to the latest openlayers dev release, now I get no errors and the response looks perfect (i.e the features on the layer in Drupal.settings.openlayers are correctly filtered to the 2 results expected) except that the actual map itself does not display the new set of features, it does not update at all.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

acbramley’s picture

Here's the ajax response I was getting on 7.x-2.0-beta5

acbramley’s picture

FileSize
24.26 KB
acbramley’s picture

With the latest dev release, I can debug $(".openlayers-map").data('openlayers').openlayers; after the ajax request is complete with $('body').ajaxComplete and I can see that the the layers still contain the old features (i.e prior to filtering).

However, the ajax response contains the correct settings in the settings merge command.

acbramley’s picture

Priority: Normal » Major

Bumping priority in hopes to get this noticed, I've done a lot of debugging, including looking at the entire diff from beta1 and trying to work out what has changed with openlayers_views

cbeier’s picture

Ok, I think I have identified the problem. All the data for the openlayers display (layers, features) are in the Drupal.settings object. If the contextual filter was used, the ajax request from views returns the correct number of features.

But in the returned JSON from Views is set, that the settings object is merged. And I think, that is the problem.

0: {command:settings, settings:{basePath:/, pathPrefix:,…}, merge:true}
command: "settings"
merge: true
settings: {basePath:/, pathPrefix:,…}
1: {command:viewsScrollTop, selector:.view-dom-id-a5615b3069e9895ded7f466e6e01c2db}
command: "viewsScrollTop"
selector: ".view-dom-id-a5615b3069e9895ded7f466e6e01c2db"
2: {command:insert, method:replaceWith, selector:.view-dom-id-a5615b3069e9895ded7f466e6e01c2db,…}
command: "insert"
data: "<div class="view view-open-layers-karte-f-r-benutzer view-id-open_layer......."
method: "replaceWith"
selector: ".view-dom-id-a5615b3069e9895ded7f466e6e01c2db"
settings: null

The Drupal ajax handling always merge the Drupal.settings object. See also:

cbeier’s picture

I have now implemented a workaround in my project. Maybe it helps somebody.

With the workaround a new command is returned in the json response from views, that manually reset the features in the layers.

/**
 * Implements hook_ajax_render_alter().
 *
 * Workaround to fix a problem with the ajax response from openlayers
 * views, when the exposed filter was used. See http://drupal.org/node/1993172
 */
function YOURMODULE_ajax_render_alter(&$commands) {
  $features = array();
  foreach ($commands as $command) {
    // Loop over the settings array, to find all features in the openlayer
    // settings.
    if ($command['command'] === 'settings' && isset($command['settings']['openlayers'])) {
      $maps = $command['settings']['openlayers']['maps'];

      foreach ($maps as $map_key => $map) {
        if (isset($map['layers']) && !empty($map['layers'])) {
          foreach ($map['layers'] as $layer_key => $layer) {
            if (isset($layer['features'])) {
              // Reset the features array.
              $features[$map_key] = array(
                'layers' => array(
                  $layer_key => array('features' => NULL),
                ),
              );
            }
          }
        }
      }
    }
  }

  if ($features) {
    array_unshift($commands, array(
      'command' => 'settings',
      'settings' => array(
        'openlayers' => array(
          'maps' => $features,
        ),
      ),
      'merge' => TRUE,
    ));
  }
}

acbramley’s picture

Interesting, I will try this out. I am wondering though what made this functionality break between the beta1 release considering nothing would've changed with the ajax response that views returns shouldn't have changed?

cbeier’s picture

I don't know it really. The ajax return for Drupal.settings will be generated, just before the result will be send to the client, from the Drupal Ajax layer. In the default ajax_command_settings() – that is responsible for Drupal.settings – should not merge. But some piece of code can change this behavior and we have the problem.

Maybe the change is not in the overlay module, but in some other (sub-)module. For example, if somewhere in the Ajax request drupal_add_js() was used, the merge param is always set to TRUE. Thus, the change in the code (between beta1 and beta5) can be very small and have this effect.

My workaround does not solve the problem. He fixes only the negative effect.

acbramley’s picture

@cbeier have tried your workaround and it did not fix my issue. The response does contain the settings replace command with the merge flag set to true and I can see that the layers and features are all set correctly, it just seems like the DOM data is not being updated. Hopefully further debugging will reveal more...

acbramley’s picture

Title: AJAX responses for views exposed filters broken » AJAX responses for views exposed filters broken (worked in beta3)

Ok, wow, I just finally reproduced the issue on a vanilla install and have discovered the unusual nature of the bug:

I have 2 nodes, A and B, both with lat lon points and a title (A and B respectively). I have a view which provides the openlayers data overlay and a map that uses that overlay with a views exposed filter of title. The behaviour I'm currently experiencing is that if the exposed filter matches the first result of the view it will filter correctly, if not it will display all points.

Adding more nodes brings even more strange behaviour, but the filtering is not working as expected.

I can confirm the ajax filtering works perfectly in 7.x-2.0-beta3 and upon upgrading to beta4 completely breaks (this is most broken version I've experienced, the map completely disappears when attempting to filter). Hopefully this provides a maintainer enough detail to find out what broke it because ajax filtering is an awesome feature!

Pol’s picture

Great, I will see what has changed and I will probably find a solution these days.

I'm not using AJAX so I don't spend time on this bug right now.

Fortunately, I'm sick and I have time to kill, so, I might find something by the end of the day ;-)

Pol’s picture

acbramley,

What you can do to help if you already have your setup, is to replace the submodule openlayers_views from beta3 into beta7 and see if it works.
Don't forget to change the projection id (4326 => EPSG:4326, etc etc), this is really important.

Thanks !

BTW, beta4 was indeed the most broken version, it includes the switch to CTools Export UI and the custom projection stuff from Augustus, I think all of this has really improved in beta7 and we are still improving it :-)

cbeier’s picture

@acbramley Ok. Maybe we have two different issues with a similar behavior.

acbramley’s picture

@Pol I've done as you requested in #12 and the behaviour is exactly the same, I have a feeling it is not openlayers_views that is at fault here as the behaviour I now get with openlayers beta7 and openlayers_views beta3 (with updated projections) is identical to what I explained in #10

Pol’s picture

Hello,

I've spent a couple of hours into this problem and I don't find a working solution, I'm looking for help.
To get help, I've prepared, thanks to acbramley, two drupal installations.

A backup of these installations has been done with drush and you can download them.

First archive: OpenLayers Working Ajax (olaw):

If you type '2' in the input filter, you'll see only 1 result on the map, which is good.

Second archive: OpenLayers Broken Ajax (olab):

How to reproduce the problem: If you type '2' in the input filter, you'll keep seeing the 2 results on the map, which is bad, even though, the AJAX response contains only one result (feature).

colinafoley’s picture

FYI

  • credentials for these sites are admin/admin.
  • olaw stands for OpenLayers Ajax Working
  • olab stands for OpenLayers Ajax Broken
colinafoley’s picture

FileSize
264.07 KB

Just as an update so no one repeats my work:

jQuery('#openlayers-map-b3afa9e9').data('openlayers').map.layers.map_openlayers_1
will get you the layer data for OLAW. I assume the "b3afa9e9" part should be static since we're using these site archives.

jQuery('#openlayers-map').data('openlayers').map.layers.map_openlayers_1
will get you the layer data for OLAB.

I inspected these because I wanted to make sure the issue wasn't with some kind of redraw of the layer. It seems the issue has more to do with the query and the layer that comes back then it does with the map replacement. This is because features array inside the layer data on OLAB has 2 elements whereas OLAW has 1 element. See the attached image.

The next area I'm going to investigate is openlayers_layer_type_openlayers_views_vector::get_features()
I ran a diff on the openlayers_views code in the 7.x-2.0-beta3 and 7.x-2.0-beta7 branches. Looking through the diff, get_features() seems like the most plausible place to start.

If you want to run a diff on these branches

git clone http://git.drupal.org/project/openlayers.git 
cd openlayers
git diff 7.x-2.0-beta3:modules/openlayers_views/ 7.x-2.0-beta7:modules/openlayers_views/
colinafoley’s picture

Looks like it's not get_features() because that seems to be returning the same set of features for both OLAW and OLAB.

Pol’s picture

Cool I can't wait to work on this tomorrow ! :-)

acbramley’s picture

I thought we confirmed it wasn't the openlayers_views module causing the issues as I ported the working version with the new projection code and the bug still existed

colinafoley’s picture

@acbramley, sorry I didn't see all of that stuff and was just working back through it all for my own sake.

@Pol, does the OLAB archive you provided have the openlayers_views files from beta7? I assume it does, but perhaps I should stop duplicating effort...

milos.kroulik’s picture

I recently contacted Geops company (authors of Cartaro distribution) and asked about their possible involvement in solving this issue. The replied, that they would happily do it for a price, which is too much for me. So I would like to find anyone, who will be able to help co-finance this work.

Mac_Weber’s picture

I've spent some time on it. I could not solve yet. By now, I can say:

The problem is NOT in:

  • openlayers.js - if you use the file beta3 and replace all ('EPSG:' + by ( it will still display the error.
  • function openlayers_views_openlayers_layers() - you can replace this function by beta3.

The problem may be in:

  • openlayers_build_map() - in the part which it hanles layer that offers the same projection as the map.
  • plugin openlayers_views_vector

Important information

The error is being caused because it is not cleaning up the map features, then it is updating the first result and keeping the second.

There are some extra lines in the OLAB's View:

colordiff view_olab.php view_olaw.php 
73,78d72
< $handler->display->display_options['defaults']['style_plugin'] = FALSE;
< $handler->display->display_options['style_plugin'] = 'openlayers_map';
< $handler->display->display_options['style_options']['map'] = 'map';
< $handler->display->display_options['defaults']['style_options'] = FALSE;
< $handler->display->display_options['defaults']['row_plugin'] = FALSE;
< $handler->display->display_options['defaults']['row_options'] = FALSE;
Pol’s picture

Hello Weber,

Thanks for your insights! I hope we'll find a solution soon.

Pol’s picture

Status: Active » Needs work
nagy.balint’s picture

This might be a crazy workaround, but seems to work for me at the moment, as for openlayers the good strategy is to always replace the map settings, this will delete the settings before the new settings gets added.

Pol’s picture

Amazing!

I will wait to get comments from others before committing it :)

Mac_Weber’s picture

@nagy.balint can you tell how did you get to this solution? Maybe it will help to find how the issue is caused.

nagy.balint’s picture

I discovered this issue last year, and then i spent some days debugging it, and got to the conclusion that it was some kind of a core issue.

Basically the issue seems to be that when you use drupal_add_js for settings then the settings will always be merged no matter what. And in the case of openlayers, where the items on the map are stored in an array, when this merge happens the number of items can only increase but not decrease. In fact the items should be replaced and not merged.

Now the settings mechanism is totally rewritten for drupal 8, but it seems there wont be any change regarding drupal 7 about this issue. One workaround i had in mind included the modification of ajax.js to handle openlayers settings differently. But of course that would have been ugly. But then today i checked this problem again. This problem will occur on all ajax reloads, but currently my goal was to fix the views ajax reload, and so i looked into the openlayers_views module. Saw that it only included one js file, and that the features are added in that js file. So the idea was to clear the features from the settings before the new ones are readded in that js. Because of course even merge is right when the other array is empty.

After that i did a few tests and it seemed to work. Maybe this is not the best solution, but seems to be a fix anyways.

Mac_Weber’s picture

Status: Needs work » Needs review

Changing to needs review.

@nagy.balint thank you for the explanation. The part I don't understand is how the old version works in the same Drupal core.

Pol’s picture

Status: Needs review » Fixed

Committed finally !

Thank you very much for your time and work all !

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

Anonymous’s picture

Issue summary: View changes

add keywords