Filters
Filters allow users to narrow a set of data based on one or more criteria.
Standard Filter
This example features an expand/collapse design that displays filters across the top of the screen.
When to Use
- This is the most common variation and should be used in most instances.
When Not to Use
- When there are only 1-2 filter categories, consider the simpler Toolbar.
Examples
- Standard Filter (shown above)
- Toolbar Simple Filter
Usage
Types of Filter Criteria
Filter categories may include a variety of form elements, such as:
Display & Behaviors
Accessing Filters
Filters are positioned at the top of the screen, above the corresponding data set. See the Filter Page Template for details on how to position the filter within the context of a screen.
Filters are hidden by default, allowing the focus to be on the initial data set.
In the Standard Filter, selecting the “Show Filters” text button expands the set of filters. In the Simple Toolbar Filter, selecting the text button or Filter icon within the Toolbar expands a popover with the filter controls.
Once the Standard Filter is expanded, up to 4 categories are displayed in the initial view (on larger screen sizes). Prioritize this view based on categories the user is most likely to use. A “Show All” option may appear in the lower left to provide access to less common categories.
A “Show All” link may also appear at the individual category level (for example, when the number of options exceeds 5-6). This may either expand more options immediately below (if there are only a few more) or launch a modal window (if there is a large number of filter values to display).
Data
It is preferred that the data update immediately as the user selects a filter criteria; if this is not technically feasible, an Apply button may appear in the lower right, below the filter set. A progress indicator may also be used in conjunction with the button if the data does not load quickly.
A Clear action may appear for an individual filter category. This allows the user to clear all selections within the corresponding category, including selections made in a modal or expanded view. While a Clear action is not always required, it is necessary to include it for certain input types that the user can’t deselect (radio buttons, for example).
Displaying Applied Filters (Tagging)
In the Standard Filter, tags may be displayed to indicate what filters have been applied. This allows the user to see what filters have been applied to the set while still allowing the filter panel to collapse. A clear all link appears next to the tags.
Tag Labels
Most input types will display the value of the filter being applied. (For example, “American Airlines” instead of “Airline: American Airlines”). In some instances, however, it is necessary to display a brief label to make the value clear (For example, filtering by number of passengers would require a label of “1 Passenger” or “Passengers: 1” instead of simply “1”). Always keep clarity in mind when determining what to display in the Applied Filters section.
Responsive Behavior
As the viewable space decreases, the filter categories collapse from four columns to three columns to two columns. At the XS screen size (view component in a new tab and adjust window size), the filter categories collapse into a series of expand/collapse panels.
The following changes also occur at the XS screen size:
- The applied filters tags do not display. Instead, a total count of the filter criteria displays in the upper left.
- A button to apply the filters appears and is locked at the bottom of the viewport.
Toolbar Simple Filter
Toolbar filter allows the ability to access a simple filter (1 or 2 categories) within a Toolbar.
Heading
Number of Tickets
Price Per Ticket
- Save Results
- Export to Excel
- Create an Alert
- Modify Search
- Advanced Search
When to Use
- Use when there are only 1 or 2 filter categories and the options within each are minimal.
When Not to Use
- Do not use for more complex filter sets.
Developer Notes
A filter component is constructed using the spark-filter
class. The filter header, created using the spark-filter__header
class, is used to display the filter toggle buttons as well tags for any applied filters. At the XS screen size, the applied tags are hidden in lieu of a tag indicating how many filters are applied. The spark-filter__content
contains the form field filter groupings and buttons that are used to filter data. The filter groups are housed within modules that respond to the screen size to adjust the number of filter groups displayed, with additional groups accessible via a view more button.
The following options may be passed when using new Spark.Filter(el, {});
:
Name | Type | Default | Description |
---|---|---|---|
onClearAll | function | null | A function to run to when clearing all tags and applied filters. |
moduleOptions | array | null | An array of options to be applied to specific filter groups/modules in order of appearance. This is detailed further below. |
The following options may be passed in the moduleOptions
array:
Name | Type | Default | Description |
---|---|---|---|
onShowAll | string | null | A string denoting the type of action to take on a show all link. The options are `modal` or `toggle`. |
onModalClose | function | null | A function to run when closing a modal via the Save button. |
onClear | function | null | A function to run to clear applied filters. |
For all available methods and full API, refer to the component code on Bitbucket.
<a class="spark-skip-nav" href="#mainContent">Skip Navigation</a>
<div class="spark-content__wrapper--sticky-footer">
<header class="spark-header">
<nav class="spark-header__nav" role="navigation">
<button class="spark-menu__toggle spark-header__toggle" aria-label="View Navigation" title="View Navigation">
<i class="spark-icon--fill spark-icon-menu-hamburger spark-icon--md"></i>
</button>
<span class="spark-header__logo"><i class="spark-logo spark-logo--sabre spark-logo--sm">Sabre</i></span>
<a href="#" class="spark-header__title">Product™</a>
<div class="spark-menu spark-header__menu" role="menu">
<div class="spark-menu__header">
<button class="spark-menu__toggle" aria-label="Hide Navigation" title="Hide Navigation">
<i class="spark-icon--fill spark-icon-close"></i>
</button>
<span class="spark-menu__title"></span>
</div>
<ul class="spark-menu__list spark-header__list spark-header__list--overflow">
<li class="spark-menu__list-item" role="menuitem">
<a href="#" class="spark-menu__list-link">Dashboard</a>
</li>
<li class="spark-menu__list-item active" role="menuitem">
<span class="spark-menu__list-links">
<a href="#" class="spark-menu__list-link">Flight Analysis</a>
<button class="spark-menu__list-expand" role="menuitemcheckbox" aria-label="Expand or Collapse Menu" title="Expand"></button>
</span>
<ul class="spark-menu__list">
<li class="spark-menu__list-item" role="menuitem">
<a tabindex="0" class="spark-menu__list-link">First Level A</a>
</li>
<li class="spark-menu__list-item" role="menuitem">
<span class="spark-menu__list-links">
<a tabindex="0" class="spark-menu__list-link">First Level B</a>
<a tabindex="0" class="spark-menu__list-expand" role="menuitemcheckbox" title="Expand"></a>
</span>
<ul class="spark-menu__list">
<li class="spark-menu__list-item" role="menuitem">
<a tabindex="0" class="spark-menu__list-link">Second Level a</a>
</li>
<li class="spark-menu__list-item" role="menuitem">
<span class="spark-menu__list-links">
<a tabindex="0" class="spark-menu__list-link spark-menu__list-expand" role="menuitemcheckbox">Second Level b</a>
</span>
<ul class="spark-menu__list">
<li class="spark-menu__list-item" role="menuitem">
<a tabindex="0" class="spark-menu__list-link">Third-level Item I</a>
</li>
<li class="spark-menu__list-item" role="menuitem">
<a tabindex="0" class="spark-menu__list-link">Third-level Item II</a>
</li>
<li class="spark-menu__list-item" role="menuitem">
<a tabindex="0" class="spark-menu__list-link">Third-level Item III</a>
</li>
<li class="spark-menu__list-item" role="menuitem">
<a tabindex="0" class="spark-menu__list-link">Third-level Item IV</a>
</li>
</ul>
</li>
<li class="spark-menu__list-item" role="menuitem">
<a tabindex="0" class="spark-menu__list-link">Second Level c</a>
</li>
<li class="spark-menu__list-item" role="menuitem">
<a tabindex="0" class="spark-menu__list-link">Second Level d</a>
</li>
</ul>
</li>
<li class="spark-menu__list-item active" role="menuitem">
<a tabindex="0" class="spark-menu__list-link">Sample Single Panel Form Page</a>
</li>
<li class="spark-menu__list-item" role="menuitem">
<a tabindex="0" class="spark-menu__list-link spark-menu__list-expand" role="menuitemcheckbox">First Level D</a>
<ul class="spark-menu__list">
<li class="spark-menu__list-item" role="menuitem">
<a tabindex="0" class="spark-menu__list-link">Second Level aa</a>
</li>
<li class="spark-menu__list-item" role="menuitem">
<a tabindex="0" class="spark-menu__list-link">Second Level bb</a>
</li>
<li class="spark-menu__list-item" role="menuitem">
<a tabindex="0" class="spark-menu__list-link">Second Level cc</a>
</li>
</ul>
</li>
</ul>
</li>
<li class="spark-menu__list-item" role="menuitem">
<span class="spark-menu__list-links">
<a href="#" class="spark-menu__list-link">Market Analysis</a>
<button class="spark-menu__list-expand" role="menuitemcheckbox" aria-label="Expand or Collapse Menu" title="Expand"></button>
</span>
<ul class="spark-menu__list">
<li class="spark-menu__list-item" role="menuitem">
<a href="#" class="spark-menu__list-link">Menu Option 1</a>
</li>
<li class="spark-menu__list-item" role="menuitem">
<span class="spark-menu__list-links">
<a href="#" class="spark-menu__list-link">Menu Option 2</a>
<button class="spark-menu__list-expand" role="menuitemcheckbox" aria-label="Expand or Collapse Menu" title="Expand"></button>
</span>
<ul class="spark-menu__list">
<li class="spark-menu__list-item" role="menuitem">
<a href="#" class="spark-menu__list-link">Sub Nav Item 1</a>
</li>
<li class="spark-menu__list-item" role="menuitem">
<a href="#" class="spark-menu__list-link">Sub Nav Item 2</a>
</li>
<li class="spark-menu__list-item" role="menuitem">
<a href="#" class="spark-menu__list-link">Sub Nav Item 3</a>
</li>
<li class="spark-menu__list-item" role="menuitem">
<a href="#" class="spark-menu__list-link">Sub Nav Item 4 That Has A Really Long Title</a>
</li>
</ul>
</li>
<li class="spark-menu__list-item" role="menuitem">
<a href="#" class="spark-menu__list-link">Menu Option 3</a>
</li>
<li class="spark-menu__list-item" role="menuitem">
<a href="#" class="spark-menu__list-link"><i aria-hidden="true" class="spark-icon-announce"></i> Menu Option 4 w/ Icon</a>
</li>
<li class="spark-menu__list-item" role="menuitem">
<a href="#" class="spark-menu__list-link">Menu Option 5 w/ A Really Long Title</a>
</li>
<li class="spark-header__list-cta">
<a href="#" class="spark-header__list-cta-link">View All Analyses</a>
</li>
</ul>
</li>
<li class="spark-menu__list-item" role="menuitem">
<a href="#" class="spark-menu__list-link">Nav Item 8</a>
</li>
<li class="spark-menu__list-item" role="menuitem">
<a href="#" class="spark-menu__list-link">Nav Item 9</a>
</li>
<li class="spark-menu__list-item" role="menuitem">
<a href="#" class="spark-menu__list-link">Nav Item 10</a>
</li>
<li class="spark-menu__list-item" role="menuitem">
<a href="#" class="spark-menu__list-link">Nav Item 11</a>
</li>
<li class="spark-menu__list-item" role="menuitem">
<a href="#" class="spark-menu__list-link">Nav Item 12</a>
</li>
</ul>
<ul class="spark-menu__list">
<li class="spark-menu__list-item spark-menu__list-item--secondary" role="menuitem">
<a href="#" class="spark-menu__list-link spark-menu__ignore" aria-label="Search">
<i class="spark-icon--fill spark-icon-search spark-icon--md"></i>
<span class="spark-header__collapsed-show">Search</span>
</a>
</li>
<li class="spark-menu__list-item spark-menu__list-item--secondary" role="menuitem">
<a href="#" class="spark-menu__list-link spark-menu__ignore" aria-label="Account Settings">
<i class="spark-icon--fill spark-icon-cog spark-icon--md"></i>
<span class="spark-header__collapsed-show">Account Settings</span>
</a>
</li>
</ul>
</div>
<div class="spark-header__sign-in spark-popover">
<a href="#" class="spark-menu__list-link spark-popover__toggle">Sign In</a>
<form class="spark-popover__content--bottom col-xs-8 col-md-4" role="tooltip" onsubmit="return false;" data-anchor-x="right">
<a href="#" class="spark-popover__close" title="Close"></a>
<h4>Account Sign In</h4>
<label class="spark-input spark-mar-t-1">
<input class="spark-input__field" name="username" role="textbox">
<span class="spark-label">Username</span>
</label>
<label class="spark-input">
<input class="spark-input__field" name="password" type="password" role="textbox">
<span class="spark-label">Password</span>
</label>
<button class="spark-btn spark-btn--md spark-btn--block">Sign In</button>
<div class="spark-text-center spark-mar-t-1">
<a href="#example-link" class="spark-link spark-zeta">Forgot username or password?</a>
</div>
<span class="spark-popover__caret"></span>
</form>
</div>
</nav>
</header>
<main class="spark-main--sticky-footer" id="mainContent">
<div class="container">
<div class="row spark-mar-b-2 spark-mar-t-2">
<div class="col-xs-12">
<h1>Page Title</h1>
</div>
<div class="col-xs-12 spark-mar-b-2">
<div class="spark-filter">
<div class="spark-filter__header">
<div class="spark-filter__toggle-container spark-clearfix">
<span class="spark-filter__result-label">128 Results</span>
<button class="spark-filter__toggle-button spark-btn spark-btn--text"><span>Show</span> Filters</button>
</div>
<div class="spark-filter__tags-container">
<div class="spark-filter__applied-filters-counter hide">
<span>0</span> Filters
</div>
<a tabindex="0" class="spark-filter__clear-all spark-zeta hide">Clear all</a>
</div>
</div>
<div class="spark-filter__content hide">
<div class="spark-filter__modules-container">
<div class="spark-filter-module" data-filter-module="module-1">
<div class="spark-filter-module__wrapper">
<div class="spark-filter-module__header">
<h4 class="spark-filter-module__title">Filter Module 1</h4>
</div>
<div class="spark-filter-module__body">
<div class="spark-filter-module__clear-container">
<button class="spark-btn spark-btn--text spark-filter-module__clear spark-filter-module__clear--disabled">Clear</button>
</div>
<fieldset class="row">
<!-- data-sync and data-sync is for custom configuration. Not a must -->
<label class="col-xs-12 spark-checkbox">
<input class="spark-checkbox__input" type="checkbox" data-sync-master="cb1" name="checkbox1"> <!-- This has to be before .spark-checkbox__box! -->
<span class="spark-checkbox__box"></span>
<span class="spark-label">Checkbox 1</span>
<span class="spark-checkbox__right-label">112</span>
</label>
<label class="col-xs-12 spark-checkbox">
<input class="spark-checkbox__input" type="checkbox" data-sync-master="cb2" name="checkbox2"> <!-- This has to be before .spark-checkbox__box! -->
<span class="spark-checkbox__box"></span>
<span class="spark-label">Checkbox 2</span>
<span class="spark-checkbox__right-label">112</span>
</label>
<label class="col-xs-12 spark-checkbox">
<input class="spark-checkbox__input" type="checkbox" data-sync-master="cb3" name="checkbox3"> <!-- This has to be before .spark-checkbox__box! -->
<span class="spark-checkbox__box"></span>
<span class="spark-label">Checkbox 3</span>
<span class="spark-checkbox__right-label">112</span>
</label>
<label class="col-xs-12 spark-checkbox">
<input class="spark-checkbox__input" type="checkbox" data-sync-master="cb4" name="checkbox4"> <!-- This has to be before .spark-checkbox__box! -->
<span class="spark-checkbox__box"></span>
<span class="spark-label">Checkbox 4</span>
<span class="spark-checkbox__right-label">112</span>
</label>
<label class="col-xs-12 spark-checkbox">
<input class="spark-checkbox__input" type="checkbox" data-sync-master="cb5" name="checkbox5"> <!-- This has to be before .spark-checkbox__box! -->
<span class="spark-checkbox__box"></span>
<span class="spark-label">Checkbox 5</span>
<span class="spark-checkbox__right-label">112</span>
</label>
</fieldset>
<div class="spark-modal" id="simpleModal">
<div class="spark-modal__scroll">
<div class="spark-modal__content col-xs-12 col-sm-10">
<div class="spark-modal__body">
<a class="spark-modal__close spark-icon-close spark-filter-module__show-all__modal-close" aria-label="Close Modal" title="Close Modal"></a>
<h4 class="spark-filter-module__show-all__modal-title">Modal Title</h4>
<div class="spark-filter-module__clear-container">
<button class="spark-btn spark-btn--text spark-filter-module__clear spark-filter-module__clear--disabled">Clear</button>
</div>
<div class="row">
<fieldset class="col-md-12 col-lg-4 ">
<label class="spark-checkbox spark-filter-module__show-all__duplicate">
<input class="spark-checkbox__input" type="checkbox" data-sync-dupe="cb1"> <!-- This has to be before .spark-checkbox__box! -->
<span class="spark-checkbox__box"></span>
<span class="spark-label">Checkbox 1</span>
<span class="spark-checkbox__right-label">112</span>
</label>
<label class="spark-checkbox spark-filter-module__show-all__duplicate">
<input class="spark-checkbox__input" type="checkbox" data-sync-dupe="cb2"> <!-- This has to be before .spark-checkbox__box! -->
<span class="spark-checkbox__box"></span>
<span class="spark-label">Checkbox 2</span>
<span class="spark-checkbox__right-label">112</span>
</label>
<label class="spark-checkbox spark-filter-module__show-all__duplicate">
<input class="spark-checkbox__input" type="checkbox" data-sync-dupe="cb3"> <!-- This has to be before .spark-checkbox__box! -->
<span class="spark-checkbox__box"></span>
<span class="spark-label">Checkbox 3</span>
<span class="spark-checkbox__right-label">112</span>
</label>
<label class="spark-checkbox spark-filter-module__show-all__duplicate">
<input class="spark-checkbox__input" type="checkbox" data-sync-dupe="cb4"> <!-- This has to be before .spark-checkbox__box! -->
<span class="spark-checkbox__box"></span>
<span class="spark-label">Checkbox 4</span>
<span class="spark-checkbox__right-label">112</span>
</label>
<label class="spark-checkbox spark-filter-module__show-all__duplicate">
<input class="spark-checkbox__input" type="checkbox" data-sync-dupe="cb5"> <!-- This has to be before .spark-checkbox__box! -->
<span class="spark-checkbox__box"></span>
<span class="spark-label">Checkbox 5</span>
<span class="spark-checkbox__right-label">112</span>
</label>
<label class="spark-checkbox">
<input class="spark-checkbox__input" type="checkbox"> <!-- This has to be before .spark-checkbox__box! -->
<span class="spark-checkbox__box"></span>
<span class="spark-label">Checkbox</span>
<span class="spark-checkbox__right-label">112</span>
</label>
<label class="spark-checkbox">
<input class="spark-checkbox__input" type="checkbox"> <!-- This has to be before .spark-checkbox__box! -->
<span class="spark-checkbox__box"></span>
<span class="spark-label">Checkbox</span>
<span class="spark-checkbox__right-label">112</span>
</label>
<label class="spark-checkbox">
<input class="spark-checkbox__input" type="checkbox"> <!-- This has to be before .spark-checkbox__box! -->
<span class="spark-checkbox__box"></span>
<span class="spark-label">Checkbox</span>
<span class="spark-checkbox__right-label">112</span>
</label>
</fieldset>
<fieldset class="col-md-12 col-lg-4">
<label class="spark-checkbox">
<input class="spark-checkbox__input" type="checkbox"> <!-- This has to be before .spark-checkbox__box! -->
<span class="spark-checkbox__box"></span>
<span class="spark-label">Checkbox</span>
<span class="spark-checkbox__right-label">112</span>
</label>
<label class="spark-checkbox">
<input class="spark-checkbox__input" type="checkbox"> <!-- This has to be before .spark-checkbox__box! -->
<span class="spark-checkbox__box"></span>
<span class="spark-label">Checkbox</span>
<span class="spark-checkbox__right-label">112</span>
</label>
<label class="spark-checkbox">
<input class="spark-checkbox__input" type="checkbox"> <!-- This has to be before .spark-checkbox__box! -->
<span class="spark-checkbox__box"></span>
<span class="spark-label">Checkbox</span>
<span class="spark-checkbox__right-label">112</span>
</label>
<label class="spark-checkbox">
<input class="spark-checkbox__input" type="checkbox"> <!-- This has to be before .spark-checkbox__box! -->
<span class="spark-checkbox__box"></span>
<span class="spark-label">Checkbox</span>
<span class="spark-checkbox__right-label">112</span>
</label>
<label class="spark-checkbox">
<input class="spark-checkbox__input" type="checkbox"> <!-- This has to be before .spark-checkbox__box! -->
<span class="spark-checkbox__box"></span>
<span class="spark-label">Checkbox</span>
<span class="spark-checkbox__right-label">112</span>
</label>
<label class="spark-checkbox">
<input class="spark-checkbox__input" type="checkbox"> <!-- This has to be before .spark-checkbox__box! -->
<span class="spark-checkbox__box"></span>
<span class="spark-label">Checkbox</span>
<span class="spark-checkbox__right-label">112</span>
</label>
<label class="spark-checkbox">
<input class="spark-checkbox__input" type="checkbox"> <!-- This has to be before .spark-checkbox__box! -->
<span class="spark-checkbox__box"></span>
<span class="spark-label">Checkbox</span>
<span class="spark-checkbox__right-label">112</span>
</label>
<label class="spark-checkbox">
<input class="spark-checkbox__input" type="checkbox"> <!-- This has to be before .spark-checkbox__box! -->
<span class="spark-checkbox__box"></span>
<span class="spark-label">Checkbox</span>
<span class="spark-checkbox__right-label">112</span>
</label>
</fieldset>
<fieldset class="col-md-12 col-lg-4">
<label class="spark-checkbox">
<input class="spark-checkbox__input" type="checkbox"> <!-- This has to be before .spark-checkbox__box! -->
<span class="spark-checkbox__box"></span>
<span class="spark-label">Checkbox</span>
<span class="spark-checkbox__right-label">112</span>
</label>
<label class="spark-checkbox">
<input class="spark-checkbox__input" type="checkbox"> <!-- This has to be before .spark-checkbox__box! -->
<span class="spark-checkbox__box"></span>
<span class="spark-label">Checkbox</span>
<span class="spark-checkbox__right-label">112</span>
</label>
<label class="spark-checkbox">
<input class="spark-checkbox__input" type="checkbox"> <!-- This has to be before .spark-checkbox__box! -->
<span class="spark-checkbox__box"></span>
<span class="spark-label">Checkbox</span>
<span class="spark-checkbox__right-label">112</span>
</label>
<label class="spark-checkbox">
<input class="spark-checkbox__input" type="checkbox"> <!-- This has to be before .spark-checkbox__box! -->
<span class="spark-checkbox__box"></span>
<span class="spark-label">Checkbox</span>
<span class="spark-checkbox__right-label">112</span>
</label>
<label class="spark-checkbox">
<input class="spark-checkbox__input" type="checkbox"> <!-- This has to be before .spark-checkbox__box! -->
<span class="spark-checkbox__box"></span>
<span class="spark-label">Checkbox</span>
<span class="spark-checkbox__right-label">112</span>
</label>
<label class="spark-checkbox">
<input class="spark-checkbox__input" type="checkbox"> <!-- This has to be before .spark-checkbox__box! -->
<span class="spark-checkbox__box"></span>
<span class="spark-label">Checkbox</span>
<span class="spark-checkbox__right-label">112</span>
</label>
<label class="spark-checkbox">
<input class="spark-checkbox__input" type="checkbox"> <!-- This has to be before .spark-checkbox__box! -->
<span class="spark-checkbox__box"></span>
<span class="spark-label">Checkbox</span>
<span class="spark-checkbox__right-label">112</span>
</label>
<label class="spark-checkbox">
<input class="spark-checkbox__input" type="checkbox"> <!-- This has to be before .spark-checkbox__box! -->
<span class="spark-checkbox__box"></span>
<span class="spark-label">Checkbox</span>
<span class="spark-checkbox__right-label">112</span>
</label>
</fieldset>
</div>
<nav class="spark-btn-group spark-filter-module__show-all__modal-button-container">
<button class="spark-btn spark-btn--sm spark-mar-l-0 spark-filter-module__show-all__modal-button">Save</button>
</nav>
</div>
</div>
</div>
</div>
<a tabindex="0" class="spark-filter-module__show-all spark-zeta">Show <span>more</span> filters</a>
</div>
</div>
</div>
<div class="spark-filter-module" data-filter-module="module-2">
<div class="spark-filter-module__wrapper">
<div class="spark-filter-module__header">
<h4 class="spark-filter-module__title">Filter Module 2</h4>
</div>
<div class="spark-filter-module__body">
<div class="spark-filter-module__clear-container">
<button class="spark-btn spark-btn--text spark-filter-module__clear spark-filter-module__clear--disabled">Clear</button>
</div>
<fieldset class="row">
<label class="col-xs-12 spark-radio">
<input class="spark-radio__input" type="radio" name="test-radio"> <!-- This has to be before .spark-radio__box! -->
<span class="spark-radio__box"></span>
<span class="spark-label">Radio 1</span>
<span class="spark-checkbox__right-label">112</span>
</label>
<label class="col-xs-12 spark-radio">
<input class="spark-radio__input" type="radio" name="test-radio"> <!-- This has to be before .spark-radio__box! -->
<span class="spark-radio__box"></span>
<span class="spark-label">Radio 2</span>
<span class="spark-checkbox__right-label">112</span>
</label>
<label class="col-xs-12 spark-radio">
<input class="spark-radio__input" type="radio" name="test-radio"> <!-- This has to be before .spark-radio__box! -->
<span class="spark-radio__box"></span>
<span class="spark-label">Radio 3</span>
<span class="spark-checkbox__right-label">112</span>
</label>
<label class="col-xs-12 spark-radio">
<input class="spark-radio__input" type="radio" name="test-radio"> <!-- This has to be before .spark-radio__box! -->
<span class="spark-radio__box"></span>
<span class="spark-label">Radio 4</span>
<span class="spark-checkbox__right-label">112</span>
</label>
<label class="col-xs-12 spark-radio">
<input class="spark-radio__input" type="radio" name="test-radio"> <!-- This has to be before .spark-radio__box! -->
<span class="spark-radio__box"></span>
<span class="spark-label">Radio 5</span>
<span class="spark-checkbox__right-label">112</span>
</label>
<div class="spark-filter-module--hide">
<label class="col-xs-12 spark-radio">
<input class="spark-radio__input" type="radio" name="test-radio"> <!-- This has to be before .spark-radio__box! -->
<span class="spark-radio__box"></span>
<span class="spark-label">Radio 6</span>
<span class="spark-checkbox__right-label">112</span>
</label>
<label class="col-xs-12 spark-radio">
<input class="spark-radio__input" type="radio" name="test-radio"> <!-- This has to be before .spark-radio__box! -->
<span class="spark-radio__box"></span>
<span class="spark-label">Radio 7</span>
<span class="spark-checkbox__right-label">112</span>
</label>
</div>
</fieldset>
<a tabindex="0" class="spark-filter-module__show-all spark-zeta">Show <span>more</span> filters</a>
</div>
</div>
</div>
<div class="spark-filter-module">
<div class="spark-filter-module__wrapper">
<div class="spark-filter-module__header">
<h4 class="spark-filter-module__title">Filter Module 3</h4>
</div>
<div class="spark-filter-module__body">
<div class="spark-filter-module__clear-container">
<button class="spark-btn spark-btn--text spark-filter-module__clear spark-filter-module__clear--disabled">Clear</button>
</div>
<div class="col-xs-12 spark-mar-b-2">
<div class="spark-range-slider spark-slider--secondary">
<label class="spark-label">Slider Label</label>
<input type="number" min="0" max="2000" value="200" title="Start">
<span class="spark-range-slider__input-divider"></span>
<input type="number" min="0" max="2000" value="1000" title="End">
<div class="spark-slider__controls">
<button class="spark-slider__handle" title="Start"></button>
<button class="spark-slider__handle" title="End"></button>
<span class="spark-slider__track">
<span class="spark-slider__track-fill"></span>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="spark-filter-module">
<div class="spark-filter-module__wrapper">
<div class="spark-filter-module__header">
<h4 class="spark-filter-module__title">Filter Module 4</h4>
</div>
<div class="spark-filter-module__body">
<div class="spark-filter-module__clear-container">
<button class="spark-btn spark-btn--text spark-filter-module__clear spark-filter-module__clear--disabled">Clear</button>
</div>
<div class="spark-input-group spark-input-group--stack spark-mar-b-1">
<label class="spark-input-group__item spark-input-group__item--primary spark-input spark-date example-double-calendar-1">
<input class="spark-input__field" type="date" role="textbox">
<span class="spark-label">Departure</span>
<a class="spark-input__addon spark-date__calendar-toggle" aria-label="Show Calendar. Only available dates are displayed." title="Show Calendar"><i class="spark-icon-calendar"></i></a>
</label>
<label class="spark-input-group__item spark-input-group__item--primary spark-input spark-date example-double-calendar-2">
<input class="spark-input__field" type="date" role="textbox">
<span class="spark-label">Arrival</span>
<a class="spark-input__addon spark-date__calendar-toggle" aria-label="Show Calendar. Only available dates are displayed." title="Show Calendar"><i class="spark-icon-calendar"></i></a>
</label>
</div>
</div>
</div>
</div>
<div class="spark-filter-module">
<div class="spark-filter-module__wrapper">
<div class="spark-filter-module__header">
<h4 class="spark-filter-module__title">Filter Module 5</h4>
</div>
<div class="spark-filter-module__body">
<div class="spark-filter-module__clear-container">
<button class="spark-btn spark-btn--text spark-filter-module__clear spark-filter-module__clear--disabled">Clear</button>
</div>
<div class="row spark-toggle-group spark-mar-t-1">
<label class="spark-toggle">
<input class="spark-toggle__input" type="radio" name="test-toggle-2-c" checked="checked">
<span class="spark-label">Flip</span>
</label>
<label class="spark-toggle">
<input class="spark-toggle__input" type="radio" name="test-toggle-2-c">
<span class="spark-label">Flop</span>
</label>
<label class="spark-toggle">
<input class="spark-toggle__input" type="radio" name="test-toggle-2-c">
<span class="spark-label">Flow</span>
</label>
</div>
</div>
</div>
</div>
<div class="spark-filter-module">
<div class="spark-filter-module__wrapper">
<div class="spark-filter-module__header">
<h4 class="spark-filter-module__title">Filter Module 6</h4>
</div>
<div class="spark-filter-module__body">
<div class="spark-filter-module__clear-container">
<button class="spark-btn spark-btn--text spark-filter-module__clear spark-filter-module__clear--disabled">Clear</button>
</div>
<div class="spark-number-selector">
<div class="spark-number-selector__item">
<input type="number" value="0" id="example-number-selector" min="0" max="22" step="2" aria-live="assertive" aria-describedby="example-number-selector__message"/>
<button class="spark-btn spark-icon spark-btn--secondary spark-icon-math-subtract spark-number-selector__down" aria-label="Less" aria-controls="example-number-selector"></button>
<button class="spark-btn spark-icon spark-btn--secondary spark-icon-math-add spark-number-selector__up" aria-label="More" aria-controls="example-number-selector"></button>
<label for="example-number-selector">
<span>Label</span>
</label>
</div>
<span id="example-number-selector__message" class="spark-input__message" role="alert"></span>
</div>
</div>
</div>
</div>
<div class="spark-filter-module">
<div class="spark-filter-module__wrapper">
<div class="spark-filter-module__header">
<h4 class="spark-filter-module__title">Filter Module 7</h4>
</div>
<div class="spark-filter-module__body">
<div class="spark-filter-module__clear-container">
<button class="spark-btn spark-btn--text spark-filter-module__clear spark-filter-module__clear--disabled">Clear</button>
</div>
<label class="spark-input spark-mar-t-1" id="filter-example-text-input">
<input class="spark-input__field" name="example1" placeholder="Enter Full Name..." role="textbox">
<span class="spark-label">What is your name?</span>
</label>
</div>
</div>
</div>
</div>
<div class="spark-filter__footer">
<button class="spark-btn spark-btn--text spark-filter__view-more-filters">View More<span class="spark-filter__toggle-caret"></span></button>
<button class="spark-btn spark-btn--text spark-filter__view-less-filters hide">View Less<span class="spark-filter__toggle-caret"></span></button>
<nav class="spark-btn-group spark-filter__apply-btn-container">
<button class="spark-btn spark-btn--sm spark-filter__btn-apply">Apply</button>
</nav>
</div>
</div>
</div>
</div>
<section class="spark-table spark-table--condensed col-xs-12">
<div class="spark-table__scroll">
<table role="grid">
<thead>
<tr>
<th data-sort>
Column 1
</th>
<th data-sort>
Column 2
</th>
<th data-sort="asc">
Column 3
</th>
<th data-sort>
Column 4
</th>
<th data-sort>
Column 5
</th>
<th data-sort>
Column 6
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
Table Item 1
</td>
<td>
Table Item 1
</td>
<td>
Table Item 1
</td>
<td>
Table Item 1
</td>
<td>
Table Item 1
</td>
<td>
Table Item 1
</td>
</tr>
<tr>
<td>
Table Item 2
</td>
<td>
Table Item 2
</td>
<td>
Table Item 2
</td>
<td>
Table Item 2
</td>
<td>
Table Item 2
</td>
<td>
Table Item 2
</td>
</tr>
<tr>
<td>
Table Item 3
</td>
<td>
Table Item 3
</td>
<td>
Table Item 3
</td>
<td>
Table Item 3
</td>
<td>
Table Item 3
</td>
<td>
Table Item 3
</td>
</tr>
<tr>
<td>
Table Item 4
</td>
<td>
Table Item 4
</td>
<td>
Table Item 4
</td>
<td>
Table Item 4
</td>
<td>
Table Item 4
</td>
<td>
Table Item 4
</td>
</tr>
<tr>
<td>
Table Item 5
</td>
<td>
Table Item 5
</td>
<td>
Table Item 5
</td>
<td>
Table Item 5
</td>
<td>
Table Item 5
</td>
<td>
Table Item 5
</td>
</tr>
<tr>
<td>
Table Item 6
</td>
<td>
Table Item 6
</td>
<td>
Table Item 6
</td>
<td>
Table Item 6
</td>
<td>
Table Item 6
</td>
<td>
Table Item 6
</td>
</tr>
<tr>
<td>
Table Item 7
</td>
<td>
Table Item 7
</td>
<td>
Table Item 7
</td>
<td>
Table Item 7
</td>
<td>
Table Item 7
</td>
<td>
Table Item 7
</td>
</tr>
</tbody>
</table>
</div>
</section>
</div>
</div>
</main>
<footer class="spark-footer">
<div class="container">
<a class="spark-footer__logo spark-hidden--lte-sm" title="Sabre"><i class="spark-logo spark-logo--sabre spark-logo--xs"></i></a>
<div class="spark-footer__content">
<div class="spark-footer__copyright">
© 2015-16 Sabre <span class="spark-hidden--lte-md">Curabitur blandit tempus porttitor.</span>
</div>
<ul class="spark-footer__list">
<li class="spark-footer__list-item">
<a class="spark-footer__list-link" href="javascript: void(0);">
Legal Policy
</a>
</li>
<li class="spark-footer__list-item">
<a class="spark-footer__list-link" href="javascript: void(0);">
Contact Us
</a>
</li>
<li class="spark-footer__list-item">
<a class="spark-footer__list-link" href="javascript: void(0);">
Support
</a>
</li>
</ul>
</div>
<ul class="spark-footer__list spark-footer__list--right spark-footer__list--icons">
<li class="spark-footer__list-item">
<a class="spark-footer__list-link" aria-label="Twitter" title="Twitter">
<i class="spark-icon-social-twitter spark-icon--fill"></i>
</a>
</li>
<li class="spark-footer__list-item">
<a class="spark-footer__list-link" aria-label="Facebook" title="Facebook">
<i class="spark-icon-social-facebook spark-icon--fill"></i>
</a>
</li>
<li class="spark-footer__list-item">
<a class="spark-footer__list-link" aria-label="LinkedIn" title="LinkedIn">
<i class="spark-icon-social-linkedin spark-icon--fill"></i>
</a>
</li>
<li class="spark-footer__list-item">
<a class="spark-footer__list-link" aria-label="Instagram" title="Instagram">
<i class="spark-icon-social-instagram spark-icon--fill"></i>
</a>
</li>
<li class="spark-footer__list-item">
<a class="spark-footer__list-link" aria-label="YouTube" title="YouTube">
<i class="spark-icon-social-youtube spark-icon--fill"></i>
</a>
</li>
</ul>
</div>
</footer>
</div>
<style type="text/css">
.white-bg {
background-color: #ffffff;
}
</style>
<style type="text/css">
</style>
// Vanilla JS
var el = document.querySelector('.spark-filter');
var headerInstance = new Spark.Filter(el);
The Filter template displayed above has been set up with only the first module (Filter Module 1) connected to functions that handle clearing, syncing with the modal, and applying of selected filters. This is because the Filter could have a variety of field configurations within each module, and as such only a single module was selected to be shown as an example.
Instantiating the Filter
The following code is provided as an example on how to instantiate a Filter with different options:
// CUSTOM CODE ILLUSTRATING HOW TO INSTANTIATE
// A FILTER WITH DIFFERENT OPTIONS
var filterInst = new Spark.Filter(el,{
onClearAll: function() {
filterInst.clearAllTagEls();
// You need custom code here to clear or reset all your applied filters
// Example: Clear all checkboxes that were checked inside Module 1
// and disable the Clear button
clearAllCheckboxes();
// Disable Clear button once we have cleared all checkboxes in Module 1
filterInst.disableModuleClearButton('module-1');
},
moduleOptions: [
{ // Module 1
onShowAll: 'modal',
onModalClose: syncWithModule,
onClear: function(){
clearAllCheckboxes();
filterInst.disableModuleClearButton('module-1');
// Set focus: If modal is open, set focus to first checkbox in modal
var modalOpen = document.querySelector('.spark-modal-open');
if (modalOpen) {
el.querySelector('#simpleModal .spark-checkbox:first-child .spark-checkbox__input').focus();
}
else {
el.querySelector('[data-filter-module=module-1] .spark-checkbox:first-child .spark-checkbox__input').focus();
}
},
},
{ // Module 2
onShowAll: 'toggle'
},
],
});
Applying filters and displaying tags
When using the Apply button to submit selected filters, it is required that you add an event listener to the button to allow you to run appropriate functions when a user clicks the button. For instance, this is the point at which tags would be applied, in and the filter collapsed to focus on the result set. The following code is provided as an example to illustrate this concept:
// CUSTOM CODE ILLUSTRATING HOW TO WORK WITH AN APPLY BUTTON
var applyBtn = el.querySelector('.spark-filter__btn-apply');
applyBtn.addEventListener('click', function(){
// Remove any existing tags
filterInst.clearAllTagEls();
var checkboxes = el.querySelectorAll('.spark-checkbox:not(.spark-filter-module__show-all__duplicate)');
var counter = el.querySelector('.spark-filter__applied-filters-counter span');
for(var i = 0; i < checkboxes.length; i++) {
var input = checkboxes[i].querySelector('input');
if(input.checked) {
var inputName = input.getAttribute('name');
var label = checkboxes[i].querySelector('.spark-label').innerHTML;
// Create the tag for each checked checkbox
filterInst.createTagEl(inputName, label, clearCheckboxTag);
// Update the counter displayed on smaller screens in lieu of the tags
counter.innerHTML = i + 1;
}
}
filterInst.toggleFilter('collapse');
});
Clearing applied filters within a module
Each module should have a Clear button that allows users to clear any selected filters, particularly in instances where an option cannot be deselected as in the case of radio buttons. By default the Clear button should be in a disabled state until the user changes a predefined value or selects an option from a set that does not have a predefined value. The following code illustrates how a Clear button can be enabled and disabled depending on a users actions:
// CUSTOM CODE ILLUSTRATING HOW TO ENABLE AND DISABLE CLEAR BUTTONS
// Determine what state the Clear button should be in
var determineClearBtnState = function(){
var showClearButton = false;
var moduleClearStatus = filterInst.moduleClearButtonStatus('module-1');
for (var i = 0; i < moduleCheckboxes.length; i++) {
if (moduleCheckboxes[i].checked) {
showClearButton = true;
}
}
if ((!showClearButton && !moduleClearStatus) || (!showClearButton && moduleClearStatus)) {
filterInst.disableModuleClearButton('module-1');
}
else if (showClearButton && !moduleClearStatus) {
filterInst.showModuleClearButton('module-1');
}
};
// Add event listeners to checkboxes
for (var i = 0; i < moduleCheckboxes.length; i++) {
moduleCheckboxes[i].addEventListener('change', determineClearBtnState.bind(moduleCheckboxes[i]));
}
Clearing an individual tag
When selected filters are applied and the filter container collapsed, the applied filters are displayed using tags, each of which has an X button to clear that specific tag. During the process of applying filters and generating of tags, each tag is supplied a callback function that is run when the user clicks the X button within the tag. The following code illustrates how a tag could be cleared and the associated checkbox unchecked:
// CUSTOM CODE ILLUSTRATING HOW TO CLEAR A CHECKBOX WHEN CLEARING AN INDIVIDUAL TAG
// This example assumes the function below was set as a callback when creating the tag on clicking of the Apply button
// filterInst.createTagEl(inputName, label, clearCheckboxTag);
var clearCheckboxTag = function (){
// 1. Find the parent of the tag clicked - this should be .spark-filter__tag and the counter tag
var tag = this.parentElement;
// 2. get the name of the checkbox that was clicked
var elementToClear = tag.getAttribute('data-filter-name');
// 3. find that checkbox and clear it, including any synced elements
var domElementToClear = document.querySelector('input[name="' + elementToClear + '"]');
if ( domElementToClear.hasAttribute('data-sync-master') ) {
var syncedAttribute = domElementToClear.getAttribute('data-sync-master');
var syncedElements = document.querySelectorAll('input[data-sync-dupe="' + syncedAttribute + '"]');
for (var i = 0; i < syncedElements.length; i++ ) {
syncedElements[i].checked = false;
}
}
domElementToClear.checked = false;
// 4. Get the number of tags currently applied
var tags = document.querySelectorAll('.spark-filter__tag');
// 5. If this is the last tag then perform clearAllTags
if (tags.length === 1) {
// If we have only 1 tag left
filterInst.clearAllTagEls();
// remove the clear button if it was applied within the module
filterInst.disableModuleClearButton('module-1');
}
// 6. Otherwise remove just this tag
else {
// 7. Remove the tag
tag.parentNode.removeChild(tag);
// 8. update counter for smaller screens as necessary
var counter = el.querySelector('.spark-filter__applied-filters-counter span');
counter.innerHTML = parseInt(counter.innerHTML) - 1; // update counter
}
};