I am having some problems using ajax to trigger an views update (D7).
Basically there is a map (leafletMap) and when it is moved/changed/zoomed, a function gets a list of node ids and triggers a views ajax refresh. Those node ids are passed into a contextual filter, so only matching packages in that view are displayed below the map.
The problem with the ajax is it often fires multiple ajax requests. When I inspect the extra requests one or two will have the correct arguments, but one will have the old arguments and then the view will refresh with the wrong nodes.
I've tried using return false
and binding what I can to this
or context
. As you can see I've tried unbind()
ing the <div />
but nothing seems to help. Often the first set of ajax calls append the wrong view, but then the next one works. And so on. To be honest I'm a bit out of my depth.
Basically I need there to be one ajax call with the correct arguments, or at least multiple ajax calls that use the correct arguments.
Any hints, ideas or suggestions would be most welcome. Many thanks.
TLDR; The below code triggers an ajax refresh of a view. This view has a contextual filter. It is triggering multiple ajax requests, some of which retain the old ajax arguments & therefore refresh incorrectly. Thanks!
Drupal.behaviors.packageFilter = {
attach: function (context, settings) {
if (typeof window.leafletMap === 'undefined' || window.leafletMap.length == 0) {
return;
}
this.leafletMap = window.leafletMap[0];
this.leafletMap.$map.once(function () {
this.leafletMap.map.on('moveend', this.refreshView.bind(this));
return false;
}.bind(this));
// Reset arguments back to default when not filtering map.
$.each(Drupal.settings.views.ajaxViews, function (key, value) {
if (value.view_name === 'packages') {
Drupal.settings.views.ajaxViews[key].view_args = '';
}
});
$('.views-exposed-form-packages-search', context).attr('action', '/packages.json');
},
refreshView: function (context, settings) {
Drupal.attachBehaviors('ViewsAjaxView');
// This gets markers from the map and converts them to node ids
var visibleMarkers = this.leafletMap.getVisibleMarkers();
var totalMarkers = this.leafletMap.markers.length;
// Do not run if map isn't filtered.
if (visibleMarkers.length < totalMarkers) {
var visibleMarkers = this.leafletMap.getVisibleMarkers();
var nids = '';
$.each(visibleMarkers, function (i, v) {
nids += v.node.nid + '+';
});
nids = nids.slice(0, -1);
// nids is an array of node ids for the view to return
$.each(Drupal.settings.views.ajaxViews, function (key, value) {
if (value.view_name === 'packages') {
// this should add the node ids as an views ajax argument
// to a contextual filter
Drupal.settings.views.ajaxViews[key].view_args = nids;
}
});
var throbber = '<div class="ajax-progress ajax-progress-throbber"><div class="throbber"> </div></div>';
$('.views-submit-button').append(throbber);
$.each(Drupal.settings.views.ajaxViews, function (key, value) {
if (value.view_name == 'packages' && value.view_args == nids) {
$('.view-id-packages').triggerHandler('RefreshView');
}
});
$('.view-id-packages').unbind();
}
}
}