NOTE: This handbook page, like all documentation on drupal.org, is a community effort. If you have any corrections please edit this page. If you have any suggestions, feature requests, or bug reports please post them in the Better Exposed Filters issue queue.
The Better Exposed Filters (BEF) module replaces the default single- or multi-select boxes that normally appear in Views' exposed filters with radio buttons or checkboxes, respectively. It can also replace date filter with a jQuery UI datepicker or yes/no filters with a single checkbox or (coming soon!) numerical filters with jQuery UI sliders. A description field or Select All/None links can be added to exposed filters to make for a better user experience. A full list of what filter options are available can be found here.
Versions
Drupal 7.x or Drupal 6.x? Views 2.x or Views 3.x? Confused? Me too...
Better Exposed Filters was recently re-versioned to make things easier:
- Drupal 6.x with Views 2.x: Use BEF 6.x-2.x
- Drupal 6.x with Views 3.x: Use BEF 6.x-3.x
- Drupal 7.x with Views 3.x: Use BEF 7.x-3.x
The Drupal 8 branch is in active development. Visit the Better Exposed Filters Drupal 8 project page.
Note: Once a final 6.x-2.0 release is made, this will become a bug-fix-only branch.
Background
Views Filters is a powerful tool that refines the results of a given view. When you expose a filter, you allow the user to interact with the view making it easy to build a customized advanced search. For example, exposing the node type field as a filter lets your site visitor limit their search queries to just blog entries. Better Exposed Filters gives you greater control over the rendering of exposed filters.
Why use this module? Try telling a client that they should click on an option, then scroll to the next option and ctrl+click on it. Don't just click 'cause you'll lose your first selection. Oh, and ctrl+click again to unselect an option. And if you're on a Mac... Yeah, not user friendly.
People understand checkboxes.
Installation
Requirements
Better Exposed Filters installs just like any other module in Drupal. Rather than repeating those instructions, I'll point you at the handbook pages devoted to this:
Drupal 5 and 6
Drupal 7
Drupal 8
BEF has been tested with the current release of Views 2.x and Views 3.x (2.9 and Alpha3, respectively, as of this writing). It should be noted that there is currently no migration path between Views 2.x and Views 3.x for BEF settings. See #714444: Need a way to upgrade BEF settings from Views 2.x to Views 3.x for more information.
All BEF settings are displayed in the exposed filter dialog (Views 2.x) or the exposed form settings dialog (Views 3.x), so there is no BEF-specific settings page.
Usage
Once installed, edit or create a view with an exposed filter. BEF only operates on fields that have a limited number of options such as Node:Type or Taxonomy:TermID. Open-ended fields, such as Node:Title, do not work with BEF. Entity References do work, however, if you Enable Render Views filters as select list (a checkbox) in the Entity's entityreference field. This is a limitation of Views and the current list of filter plugins. Consider adding a feature request to the Views issue queue if a filter you need is unavailable to BEF.
The BEF options show up in different places between Views 2.x and Views 3.x. In Views 2.x you can find the BEF options right alongside the other exposed filter options.
Views 3.x introduced the concept of exposed form plugins. Now getting BEF to operate is a two step process:
- Edit the view in question
- In the Exposed form block click on the link besides Exposed form style and select Better Exposed Filters from the options. In Drupal 7, the Exposed form block is located in the Advanced section.
- When you click Update you will be presented with the various BEF options available for your filters. To return to this settings form, click the gear icon besides Exposed form style. In Drupal 7, you return to the settings page by clicking the BEF settings link instead.
Styling Better Exposed Filters
BEF provides some additional HTML structure to help you style your exposed filters. Here are some common examples. You can use Views exposed form layout module to group fields by regions.
Optgroups
Optgroups allow you add a basic hierarchy to a select element. If you are listing locations, you might group them by country. In a CCK field, you would set the "Allowed values" to PHP and include code similar to:
return array(
'MX' => 'Mexico',
'United States' => array(
'AL' => 'Alabama',
'AK' => 'Alaska',
'AZ' => 'Arizona',
...
),
'Canada' => array(
'AB' => 'Alberta',
'BC' => 'British Columbia',
'MB' => 'Manitoba',
...
),
);
(With apologies to Mexico -- I know there are Mexican states, but I wanted to show top-level and optgroup options...)
The browser handles the display of optgroups in select elements. To style BEF checkboxes similarly, you would add CSS code similar to:
.bef-group-heading {
font-weight: bold;
}
.bef-group-items {
margin-left: 1.5em;
}
Or get a little more fancy with something like:
.bef-group-heading {
font-weight: bold;
padding-left: .5em;
}
.bef-group-items {
margin: 0 0 .5em .75em;
padding: .5em 0 0 .75em;
border-left: 1px dotted #666;
border-bottom: 1px dotted #666;
}
A long list of checkbox or radio button options can be just as poor a user experience as the original. To tame a long list of options, consider placing them within a scrollable region. BEF adds the necessary HTML structure to do this with just a little CSS:
.bef-checkboxes,
.bef-select-as-radios .form-radios {
/*
* Setting the height and overflow creates a scrollable <div> for the radio/checkbox elements.
* The border is just for looks -- adjust or remove as needed.
*/
height: 150px;
overflow: auto;
border: 1px solid #999;
}
/* Line up multi-line options nicely */
.bef-checkboxes .form-item,
.bef-select-as-radios .form-radios .form-item {
text-indent: -24px;
margin-left: 24px;
}
Select All/None link
The (optional) select all/none link can be styled using the .bef-toggle selector. For example:
.bef-toggle {
text-align: right;
font-size: 85%;
display: block;
}
Tooltip-style help text
Better Exposed Filters allows you to add a description field to any exposed filter. This lets you provide contextual help to your site visitors, for example letting them know that a Node:Title exposed filter requires them to enter the exact title. (Unless you've changed the "Operator" settings).
If you don't want the descriptions cluttering your display, you can show/hide them using something similar to this:
if (Drupal.jsEnabled) {
$(document).ready(function() {
$('div.views-exposed-widget')
.hover(function() {
$('div.description', this).slideDown(250);
}, function() {
$('div.description', this).slideUp(250);
})
.find('div.description')
.hide()
;
});
}
Instant filter results using AJAX
Providing instant feedback of filter changes can also improve the user experience. Using Views' built-in AJAX paging and a little JavaScript, we can update the search results every time the user ticks a checkbox or changes a radio button option.
In your view, under the "Basic settings" section set AJAX to "No". Add the following JavaScript to your theme. This is best done with in a custom JavaScript file, but could be done using drupal_add_js() from your theme's template.php file in a pinch.
Drupal 6:
Drupal.behaviors.bef_live_filter = function(context) {
// Only execute on first document ready
if (context.nodeName == '#document') {
// Hide the apply button.
$('.views-exposed-form input:submit').hide();
// When the change event fires, run the submit handler
$('.views-exposed-form input').change(function(event) {
$(this).parents('form').submit();
});
}
}
(Thanks to bkosborne for correcting this snippet).
This code assumes there is only one set of exposed filters on the page. The wait cursor will appear where the Apply button used to be.
Drupal 7:
(function($) {
Drupal.behaviors.bef_live_filter = {
attach: function(context, settings) {
// Hide the apply button.
$('.views-exposed-form input:submit', context).hide();
// When the change event fires, run the submit handler
$('.views-exposed-form input, .views-exposed-form select', context).change(function(event) {
$(this).parents('form').find('.views-exposed-form input:submit').click();
});
}
}
})(jQuery);
Alternative solutions:
- Alternatively you could use the Views Hacks module that seems to work very well, and also give you the ability to add a RESET button to exposed filters.
Using the jQuery Slider widget with the "In between" filter
NOTE: The 7.x-3.x branch has support for jQuery Sliders and Datepickers built into BEF. The following is only for the 6.x branch.
While outside the scope of the Better Exposed Filters project, this was a common request in the issue queue so I'm including a recipe for it here.
For numeric data types, Views provides an "In between" filter which can be exposed. This allows a site visitor to limit their search by a price range, for example. The jQuery UI project offers an excellent slider widget which provides a visual version of this filter. One could also vary this recipe to work with "less than" or "greater than" filters.
- Download, install and enable version 2.x of the jQuery Update module. This includes jQuery 1.3 or greater.
- Go to jQuery UI download page
- Select 1.7.x in the right-hand "Version" sidebar
- Check the "Core" and "Slider" checkboxes (and others, if you wish)
- Optionally, select a theme
- Click download
- Unzip the downloaded file
- Place
js/jquery-ui-1.7.2.custom.min.js and css/jQuery-UI-theme-name/jquery-ui-1.7.2.custom.css into your theme directory, for example, /sites/example.com/themes/my_theme/includes/jquery-ui-1.7.2.custom.min.js and /sites/example.com/themes/my_theme/includes/jquery-ui-1.7.2.custom.css
- Optionally, copy the
css/jQuery-UI-theme-name/images directory into the same location as the jquery-ui-1.7.2.custom.css file
- Edit your theme's info file to include these two new files. If you don't already have one, add a custom.js (or similar) file while you're there.
- Create a new View
- Add a filter for a numeric field
- Click "Expose"
- Select "Is between" for the operator
- Set the "Filter identifier" to something something that describes the filter -- the default option is fine, though a bit long. In this example, I use "slider_filter" which doesn't exactly describe the filter, but this is just an example...
- Click update and save the view
- Add the following code to your
custom.js:
if (Drupal.jsEnabled) {
Drupal.behaviors.test = function() {
// NOTE: the exposed filter was given a filter identifier of "slider_filter". Views
// adds the "edit-" and "-min/-max" parts.
var min = $('input#edit-slider-filter-min');
var max = $('input#edit-slider-filter-max');
if (!min.length || !max.length) {
// No min/max elements on this page
return;
}
// Set default values or use those passed into the form
var init_min = ('' == min.val()) ? 0 : min.val();
var init_max = ('' == max.val()) ? 10 : max.val();
// Set initial values of the slider
min.val(init_min);
max.val(init_max);
// Insert the slider before the min/max input elements
min.parents('div.views-widget').before(
$('<div></div>').slider({
range: true,
min: 0, // Adjust slider min and max to the range
max: 10, // of the exposed filter.
values: [init_min, init_max],
slide: function(event, ui){
// Update the form input elements with the new values when the slider moves
min.val(ui.values[0]);
max.val(ui.values[1]);
}
})
); // Add .hide() before the ';' to remove the input elements altogether.
};
}
- Optionally, add some additional CSS code to your theme's main CSS file. This example put the input elements on a single line:
#edit-slider-filter-max-wrapper,
#edit-slider-filter-min-wrapper,
#edit-slider-filter-max-wrapper label {
margin-top: 5px;
display: inline-block;
}
#edit-slider-filter-min,
#edit-slider-filter-max {
width: 30px;
}
#edit-slider-filter-max-wrapper label {
width: 75px;
text-align: center;
}
- Navigate to the page containing the view created above.