1

In attempting an AJAX refresh on several views contained in separate blocks on a single page, I seem to be coming across a problem. This is running on D7.34

The idea is for the page to contain 4 blocks, each with a view sorting by random - then using a simple click() on the block title to activate a refresh of any given view allowing the user to view a new random item. I am using the common:

var selector = '.view-dom-id-' + dom_id;
jQuery(selector).triggerHandler('RefreshView');

to achieve this, which works perfectly. The trouble I am having is in increasing multiples of refreshes:

clicking on one view refresh does refresh the view, but it seems to create a counter, when a different view is refreshed, that second view refreshes twice. Then going back to the first, the view would refresh 3 times, and so on. It doesn't happen if clicking on the same view multiple times - in this case it only refreshes once as expected, it only occurs when switching between refreshing different views, however it continues to "count" these refreshes which then effect the number of times a different view is refreshed when the other refresh is triggered.

  • I have confirmed that the selector is correct and obtains the unique dom_id for that view
  • I have confirmed that the call jQuery(selector).triggerHandler('RefreshView'); only occurs once per click
  • this occurs in Drupal.Behaviours, drupal_add_js, and straight JS added to a tpl file - they all "work" but with the same refresh issue
  • I have used once() in the call as well with no perceived effect

It seems like when the triggerHandler triggers the refresh, the view itself is refreshing multiple times for reasons I can't seem to figure out. I have tried dozens of permutations now without any change in behaviour. I can't post of all the code from my attempts, but here is the last attempt which "works" but still refreshes multiple times - this is a straight JS addition to page.tpl, layed out for easier reading:

<script>
  jQuery(document).ready(function()
  {
    jQuery('#block-views-random-cat-block h2').click(function()
    {
      jQuery.each(Drupal.views.instances, function(i, view)
      {
        if (view.settings.view_name == "random_cat")
        {
          var selector = '.view-dom-id-' + view.settings.view_dom_id;
          jQuery(selector).triggerHandler('RefreshView');
        }
      });
    });

    jQuery('#block-views-random-dog-block h2').click(function()
    {
      jQuery.each(Drupal.views.instances, function(i, view)
      {
        if (view.settings.view_name == "random_dog")
        {
          var selector = '.view-dom-id-' + view.settings.view_dom_id;
          jQuery(selector).triggerHandler('RefreshView');
        }
      });
    });
  });
</script>

If I limit the page to one view only, it seems to work fine - it's only in the fact that there are multiple views that I see this effect.

1
  • Try binding the behaviour/action with jQuery .once(), perhaps put it into the chain just before the click binding. You mention you tried it, but I will persist with pursuing a solution using that. Commented Nov 29, 2014 at 5:17

2 Answers 2

1

EDITED ANSWER

This seems to work now. Checked via the spinner and a console.log statement. Had to chain once() just before click binding. :

(function ($) {
    Drupal.behaviors.blockRefresh = {
        attach: function (context, settings) {
            jQuery('#block-views-block-1-block h2').once().click(function () {
                    jQuery.each(Drupal.views.instances, function (i, view) {
                        var selector = '.view-dom-id-' + view.settings.view_dom_id;
                        if (view.settings.view_display_id == "block") {
                            console.log('1');
                            jQuery(selector).triggerHandler('RefreshView');
                        }
                        jQuery(selector).unbind();
                    });
                });


            jQuery('#block-views-block-1-block-1 h2').once().click(function () {
                    jQuery.each(Drupal.views.instances, function (i, view) {
                        var selector = '.view-dom-id-' + view.settings.view_dom_id;
                        if (view.settings.view_display_id == "block_1") {
                            console.log('2');
                            jQuery(selector).triggerHandler('RefreshView');
                        }
                        jQuery(selector).unbind();

                    });
                });

            jQuery('#block-views-block-1-block-2 h2').once().click(function () {
                    jQuery.each(Drupal.views.instances, function (i, view) {
                        var selector = '.view-dom-id-' + view.settings.view_dom_id;
                        if (view.settings.view_display_id == "block_2") {
                            console.log('3');
                            jQuery(selector).triggerHandler('RefreshView');
                        }
                        jQuery(selector).unbind();
                    });
                });

        }
    }
}(jQuery));
8
  • this didn't seem to have an effect for me (or at least not the desired effect) - it caused first click to refresh 3 times, regardless, and then subsequent clicks on other views to refresh in counts of 3... 3 6 9 12, etc. I also tried incorporating once() further up the chain as your comment to the question suggested but without effect...
    – Geoff
    Commented Nov 29, 2014 at 18:31
  • Have you done this for each of your other click events also (random-cat)? I did it this side and it worked perfectly. And just check what version of jQuery you are using as I think 'unbind' might have gotten deprecated circa 1.7, so just use the equivalent. For completeness I am posting my complete solution that worked (used multiple block displays on same view). Commented Nov 30, 2014 at 3:39
  • I also tried this without success (with my code posted above). My code does not loop through the views instances every click, but I'm not sure if this would make a difference.
    – 2pha
    Commented Nov 30, 2014 at 4:01
  • @2pha I think in your case it will make a difference as it only needs to unbind the bound event when it is not a match. In your case it will unbind irrespective (OR condition). And I just re-tested my solution and it works fine (tried with jquery version 1.5 and 1.10 no problem). Commented Nov 30, 2014 at 5:44
  • Actually, I just tested it with a console.log and you are right. It does not work. I was just looking at the ajax spinner which previously doubled up and with this solution remained single. Commented Nov 30, 2014 at 6:04
2

This is not really an answer, but I put it here so I could format my code.

This seems to me like it may be a bug.

I have been playing around with this for about an hour and a half now and could not get it to work as expected when I had more than 1 view on a single page.

To test I made a view called 'testing' with 2 blocks with the names 'block_1' and 'block_2'. I placed both of these blocks on a single page and added the code below to refresh them via ajax when clicking the heading.

code:

(function ($) {
  Drupal.behaviors.myAjax = {
    attach: function (context, settings) {

      jQuery.each(Drupal.views.instances, function(domid, view){

        if(view.settings.view_name == 'testing' && view.settings.view_display_id == 'block_1' || 
           view.settings.view_name == 'testing' && view.settings.view_display_id == 'block_2') {

          jQuery('#block-views-'+view.settings.view_name+'-'+view.settings.view_display_id.replace('_', '-')+' h2', context).once().click(function(){
            jQuery(view.element_settings.selector).triggerHandler('RefreshView');
          });
        }
      });
    }
  };

})(jQuery);

This ended up with the same behavior as the OP.

I think you should file a issue report in the views module issue queue

1

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.