Auto-refreshing views for real-time information streams

Imagine you are creating an activity stream for your site. You'd like to use Views because it gives you all the power you need to query items and style them on the page - all in time for your 11am nap. However, the resulting page is static and users have to keep refreshing it manually to see updates. In 2011, that's just uncool.

That's why I created Views Auto-Refresh, a Views Hacks sub-module that implements an auto-refreshing mechanism that integrates right into Views 2 or 3. Here's how it works:

  • Define your view normally, and turn on Ajax.
  • In the view header, enter the following PHP code:
$interval = 15000; // 15000 msec = 15 sec
print theme('views_autorefresh', $interval);
  • Turn on the "Display even if view has no result" option for the header.

Now, automagically, your view will be refreshed every 15 seconds.

Advanced Usage

That's pretty cool, but your server ends up re-querying the same items every 15 seconds, for each user on that page, which is a bit scary. To alleviate the problem a bit, Views Auto-Refresh includes a more advanced mode for "incremental" refresh. The main idea is to create a secondary view, hopefully less heavy than the first one, that only returns new items since the last refresh. The module is responsible for merging those new items into the existing items on the page. Here's how that works in its simplest form:

  • Define a secondary view that is a clone of the original (e.g. another page display of the same view).
  • Give it a unique path, say my_view/autorefresh.
  • Add to this secondary view an argument of type Node: Post date (with operator) - or any other timestamp that makes sense in your case. These arguments are supplied by Views Auto-Refresh.
  • Change the header script above to:
$interval = 15000; // 15000 msec = 15 sec
print theme('views_autorefresh', $interval, array(
  'view_base_path' => 'my_view/autorefresh',
  'view_display_id' => 'page_2',
  'view_name' => 'my_view',
  'sourceSelector' => '.view-content',
  'targetSelector' => '.view-content',
  'firstClass' => 'views-row-first',
  'lastClass' => 'views-row-last',
  'oddClass' => 'views-row-odd',
  'evenClass' => 'views-row-even',
));

The additional settings are used to inform Views Auto-Refresh on which secondary view to hit (given its name, display and path), as well as how to merge the items from the source (the secondary view) into the target (the primary, on-screen view). The code will fetch all items inside the sourceSelector container and prepend them to the targetSelector. Then, it will fix up the odd/even, first/last and row number classes based on the settings.

Integration with other Views features

So far, this module has been successfully tested with exposed filters. Clicking on an exposed filter disables the auto-refresh to allow the user to complete the interaction without disruption.

Future work

A bullet-point roadmap is outlined on the module's issue queue.

Comments

I'm using Views Auto Refresh in 3 view panes of the same view and then I add those panes in a page. The problem is that only one of the views refresh and I want that the 3 refresh. Any fix for this???

Thanks

Is there a way that the same effect can be achieved "on-click" rather than auto-refreshed with time interval?

Thanks

Greg

Not at the moment, but I think there's already a feature request for that. Otherwise, feel free to submit one.

Thanks, any other method already built you know of that would achieve a similar outcome?

Nothing I know that does this out of the box. If you're desperate, create an exposed filter on an ajax view, then hide the filter element using CSS and only show the "Apply" button. This would work I think :-)

Hi, I am trying to make same feature and uploaded the auto_fresh views module enable it but in drupal 7 there is no option of putting code in the header. i did that via views_php module but still it is not working for me.

Can you please help me where i am doing wrong?

You need to turn on the PHP filter module in Drupal core, then add a new text area in the view header with text format "PHP code". That's where you place your code.

Thanks for your quick reply. i enable the php filter. and i put the code in. but still no luck. although my view is a block. it is gonna work for blocks or just for pages?

I am using view hacks module and i make ajax "Yes" in view. And put your php code in header. I set interval with 30 seconds, But it auto refresh only in 5 seconds.

Here is the code that i used in view header:-

<?php
$interval
= 30000;
print
theme('views_autorefresh', $interval);
?>

Will you please let me know what's going wrong?

Thanks in advance!

Not sure. Please submit a support request on the Views Hacks issue queue.

hi

Just wondering in the example are you now using the clone as your view, or is the clone used to inform the first view of new updates.

And secondly is the 4th point, where you change the header script, are you changing that code in the clone or in the original view?

Thanks for any help

1) The clone is just used to return new updates. That's why it has the extra argument. The original view is still used to render the whole page.

2) The header script is changed in the original view.

I added support for 3rd party modules that need to do extra work when new items are added.

For example, Views Fluid Grid uses jQuery Masonry to provide a fluid grid layout. When the page is loaded, the masonry() function is called on the view container. But when the view is auto-refreshed, the layout is not refreshed to account for new items.

My solution is to invoke a custom JavaScript event called "autorefresh" whenever new items are inserted as a result of auto-refresh. This event is triggered on the view container, so a 3rd party module would do something like:

Drupal.behaviors.fixViewsFluidGrid = function(context) {
  $('.view').bind('autorefresh', function() {
    $('.views-fluidgrid-wrapper', this).masonry('reload');
  });
}

which invokes the relevant Masonry API to refresh the view.

On the server side, the hook hook_views_autorefresh_plugins is used to signal that we're injecting an auto-refresh script to the view. Interested 3rd party modules can add their own JavaScript files at that point.

Forgot to mention the very important step of turning on the "Display even if view has no result" option in the header. That's now fixed.

Someone asked if it was possible to auto refresh only part of a page, just to let you know. There is away to auto refresh part of a page or many parts of a page. you need to make a seperate page for each part you wish to auto refresh, then put these pages in iFrames with sizes and with or without borders. Each part can be set to auto refresh at differant times. check out the source code of my website to see what i have done. And Good Luck With Your Project! Ian

Working php code

<?php
$interval
= 30000; // 15000 msec = 15 sec
$variables['interval']=$interval;
print
theme_views_autorefresh($variables)
?>