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:
$interval = 15000; // 15000 msec = 15 sec
print theme('views_autorefresh', $interval);
Now, automagically, your view will be refreshed every 15 seconds.
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:
$interval = 15000; // 15000 msec = 15 sec
print theme('views_autorefresh', $interval, views_get_current_view(), 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.
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.
A bullet-point roadmap is outlined on the module's issue queue.
Comments
I wrote a follow-up post on
I wrote a follow-up post on optimizing the ping process to reduce server load.
I added support for 3rd party
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_autorefreshis 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
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.