Searchbar
Searchbar allows user to search through List View elements. Or it can be used as a visual UI component for your custom search realization.
Searchbar Layout
<div class="searchbar-backdrop"></div>
<form class="searchbar">
<div class="searchbar-inner">
<div class="searchbar-input-wrap">
<input type="search" placeholder="Search">
<i class="searchbar-icon"></i>
<span class="input-clear-button"></span>
</div>
<span class="searchbar-disable-button">Cancel</span>
</div>
</form>
Where:
<div class="searchbar-input-wrap">
- wrapper for search field and clear button<input type="search">
- search field<i class="searchbar-icon">
- search icon<span class="input-clear-button">
- button to clear field value and reset search results. Optional element
<span class="searchbar-disable-button">
- Searchbar “Cancel” button that will deactivate Searchbar, reset search results and clear search field. Optional element<div class="searchbar-backdrop">
- semi transparent searchbar backdrop that becomes visible when we enable searchbar. It is recommended to place this element inside of scrollable page’spage-content
Searchbar Type
Now let’s see where we can place Searchbar in page structure. There are few options:
Fixed Searchbar
Fixed Searchbar is always visible on screen not depending on page scroll. In this case it must be placed according to one of the following rules:
It can be a direct child of page and if page has also fixed Navbar and/or Toolbar then it must be AFTER Navbar and Toolbar:
<div class="page">
<div class="navbar">...</div>
<div class="toolbar toolbar-bottom">...</div>
<!-- Searchbar goes after Navbar and Toolbar -->
<form class="searchbar">...</form>
<div class="page-content">
<!-- Searchbar backdrop layer -->
<div class="searchbar-backdrop"></div>
<!-- page content here -->
</div>
</div>
It can be placed inside of Subnavbar which is inside of the Navbar (recommended way):
<div class="page page-with-subnavbar">
<div class="navbar">
<div class="navbar-bg"></div>
<div class="navbar-inner">
...
<div class="subnavbar">
<!-- Searchbar inside of Subnavbar -->
<form class="searchbar">...</form>
</div>
</div>
</div>
<div class="page-content">
<!-- Searchbar backdrop layer -->
<div class="searchbar-backdrop"></div>
<!-- page content here -->
</div>
</div>
Static Searchbar
In this case Searchbar is just part of the scrollable page content:
<div class="page">
<div class="navbar">...</div>
<div class="page-content">
<!-- Searchbar backdrop layer -->
<div class="searchbar-backdrop"></div>
<!-- Searchbar is part of scrollable page content -->
<form class="searchbar">...</form>
<!-- page content here -->
</div>
</div>
Expandable Searchbar
Expandable Searchbar is hidden when disabled and becomes visible when we enable it. Its layout is pretty strict, it must be placed inside of Navbar:
<div class="page">
<div class="navbar">
<div class="navbar-bg"></div>
<div class="navbar-inner">
<div class="left">...</div>
<div class="title">...</div>
<div class="right">
<!-- Link to enable searchbar -->
<a class="link icon-only searchbar-enable" data-searchbar=".searchbar">
<i class="icon f7-icons if-not-md">search</i>
<i class="icon material-icons md-only">search</i>
</a>
</div>
<!-- Searchbar is a direct child of "navbar-inner" -->
<form class="searchbar searchbar-expandable">
<div class="searchbar-inner">
<div class="searchbar-input-wrap">
<input type="search" placeholder="Search"/>
<i class="searchbar-icon"></i>
<span class="input-clear-button"></span>
</div>
<span class="searchbar-disable-button">Cancel</span>
</div>
</form>
</div>
</div>
<!-- Scrollable page content -->
<div class="page-content">...</div>
</div>
Where:
<a class="link icon-only searchbar-enable" data-searchbar=".searchbar">
- link to enable/expand Searchbar. Optional or can be placed in any other place.data-searchbar
attribute contains CSS selector of Searchbar to enable.- Searchbar has additional
searchbar-expandable
class. It is required for expandable Searchbar to work
Inline Searchbar
Inline Searchbar is designed to be used inside of other components, specifically inside of Appbar. It has simplified layout - without .searchbar-inner
, and it is recommended to use it without disable button.
We just need to add searchbar-inline
class to Searchbar to make it inline
<!-- Additional "searchbar-inline" class -->
<div class="searchbar searchbar-inline">
<div class="searchbar-input-wrap">
<input type="search" placeholder="Search">
<i class="searchbar-icon"></i>
<span class="input-clear-button"></span>
</div>
</div>
Searchbar Behavior Classes
There are also several CSS classes that can be added to elements that will define their behavior when Searchbar is active:
searchbar-hide-on-enable
- elements with such class on page will be hidden when searchbar is enabledsearchbar-hide-on-search
- elements with such class on page will be hidden during searchsearchbar-not-found
- elements with such class are hidden by default and become visible when there is not any search resultssearchbar-found
- elements with such class are visible by default and become hidden when there is not any search resultssearchbar-ignore
- searchbar will not consider this elements in search results
For example:
<div class="page">
<div class="navbar">...</div>
<div class="page-content">
<div class="searchbar-backdrop"></div>
<form class="searchbar">...</form>
<!-- Following block title and block will be hidden on search -->
<div class="block-title searchbar-hide-on-search">Some block title</div>
<div class="block">Lorem ipsum dolor sit amet...</div>
<!-- We do search in super heroes list so the following title and list must be visible on search -->
<div class="block-title searchbar-found">Super Heroes</div>
<div class="list simple-list searchbar-found">
<ul>
<li>Hulk</li>
<li>Batman</li>
<li>Superman</li>
...
</ul>
</div>
<!-- This list will be visible when there is not any search results -->
<div class="list simple-list searchbar-not-found">
<ul>
<li>Nothing found</li>
</ul>
</div>
</div>
</div>
Searchbar App Methods
Now, when we have Searchbar’ HTML, we need to initialize it. We need to use related App’s method:
app.searchbar.create(parameters) | Initialize Searchbar with parameters
|
app.searchbar.destroy(el) | Destroy Searchbar instance
|
app.searchbar.get(el) | Get Searchbar instance by HTML element
|
app.searchbar.clear(el) | Clear Searchbar text input
|
app.searchbar.enable(el) | Enable Searchbar
|
app.searchbar.disable(el) | Disable Searchbar
|
app.searchbar.toggle(el) | Toggle Searchbar: enable if it was disabled, or disable if it was enabled
|
app.searchbar.search(el, query) | Trigger searchbar to search query
|
Searchbar Parameters
Let’s look on list of all available parameters we need to create/init Searchbar:
Parameter | Type | Default | Description |
---|---|---|---|
el | string HTMLElement | CSS selector or HTML element of searchbar element (form class=”searchbar” ) | |
inputEl | string HTMLElement | CSS selector or HTML element of searchbar input element. By default (if not passed) will try to look for input type=”search” inside of searchbar | |
disableButton | boolean | true | Enables disable button |
disableButtonEl | string HTMLElement | CSS selector or HTML element of searchbar disable button. By default (if not passed) will try to look for element with search-disable-button class inside of searchbar | |
searchContainer | string HTMLElement | CSS selector or HTML element of list block to search in | |
searchIn | string | CSS selector of List View element’s field where we need to search. Usually we search through element titles, in this case we need to pass .item-title . It is also possible to pass few elements for search like .item-title, .item-text | |
searchItem | string | li | CSS selector of single search item. If we do a search in List View, then it must be a single list element li |
searchGroup | string | .list-group | CSS selector of group element. Used when hideGroups enabled to hide groups. If we do a search in List View, then it usually a list group. |
searchGroupTitle | string | .list-group-title, .item-divider | CSS selector of group titles and dividers. Used when hideDividers enabled to hide group titles and dividers. If we do a search in List View, then it usually a list group title or list item divider. |
foundEl | string HTMLElement | .searchbar-found | CSS selector or HTMLElement of searchbar “found” element to make it hidden when there is no search results |
notFoundEl | string HTMLElement | .searchbar-not-found | CSS selector or HTMLElement of searchbar “not-found” element to make it visible when there is no search results |
hideOnEnableEl | string HTMLElement | .searchbar-hide-on-enable | CSS selector or HTMLElement of elements to be hidden when searchbar enabled |
hideOnSearchEl | string HTMLElement | .searchbar-hide-on-search | CSS selector or HTMLElement of elements to be hidden on searchbar search |
backdrop | boolean | Enables searchbar backdrop element. By default, disabled for Aurora theme or for inline searchbar | |
backdropEl | string HTMLElement | CSS selector or HTMLElement of searchbar backdrop element. If not passed and backdrop parameter is true then it will look for .searchbar-backdrop element. In case none found it will create one automatically | |
ignore | string | .searchbar-ignore | CSS selector for items to be ignored by searchbar and always present in search results |
customSearch | boolean | false | When enabled searchbar will not search through any of list blocks specified by searchContainer and you will be able to use custom search functionality, for example, for calling external APIs with search results and for displaying them manually |
removeDiacritics | boolean | false | Enable to remove/replace diacritics (á, í, ó, etc.) during search |
hideDividers | boolean | true | If enabled, then search will consider item dividers and group titles and hide them if there are no found items right after them |
hideGroups | boolean | true | If enabled, then search will consider list view groups hide them if there are no found items inside of these groups |
on | object | Object with events handlers. For example:
|
Searchbar Methods & Properties
To create a Searchbar we have to call:
var searchbar = app.searchbar.create({ /* parameters */ })
After we initialize Searchbar we have its initialized instance in variable (like searchbar
variable in example above) with helpful methods and properties:
Properties | |
---|---|
searchbar.params | Object with passed initialization parameters |
searchbar.query | Current search query (search input value) |
searchbar.previousQuery | Previous search query (search input value) |
searchbar.searchContainer | Searchbar search container |
searchbar.$searchContainer | Dom7 element with searchbar search container |
searchbar.el | Searchbar HTML element. |
searchbar.$el | Dom7 element with searchbar HTML element. |
searchbar.inputEl | Searchbar input HTML element |
searchbar.$inputEl | Dom7 element with searchbar input HTML element |
searchbar.enabled | Boolean value that represents is searchbar enabled or disabled |
searchbar.expandable | Boolean value that represents is searchbar expandable or not |
Methods | |
searchbar.search(query); | Force searchbar to search passed query |
searchbar.enable(); | Enable/activate searchbar |
searchbar.disable(); | Disable/deactivate searchbar |
searchbar.toggle(); | Toggle searchbar |
searchbar.clear(); | Clear search query and update results |
searchbar.destroy(); | Destroy searchbar instance |
searchbar.on(event, handler) | Add event handler |
searchbar.once(event, handler) | Add event handler that will be removed after it was fired |
searchbar.off(event, handler) | Remove event handler |
searchbar.off(event) | Remove all handlers for specified event |
searchbar.emit(event, …args) | Fire event on instance |
Searchbar Events
Searchbar will fire the following DOM events on searchbar element and events on app and searchbar instance:
DOM Events
Event | Target | Description |
---|---|---|
searchbar:search | Searchbar Element<form class=”searchbar”> | Event will be triggered during search (search field change). Event detail (e.detail) contains search query |
searchbar:clear | Searchbar Element<form class=”searchbar”> | Event will be triggered when user clicks on Searchbar’s “clear” element (a href=”#” class=”searchbar-clear”). Event detail (e.detail) contains previous (before clear) search query |
searchbar:enable | Searchbar Element<form class=”searchbar”> | Event will be triggered when Searchbar becomes active/enabled |
searchbar:disable | Searchbar Element<form class=”searchbar”> | Event will be triggered when Searchbar becomes disabled/inactive - when user clicks on “Cancel” button (a href=”searchbar-cancel”) or on “searchbar-overlay” element |
searchbar:beforedestroy | Searchbar Element<form class=”searchbar”> | Event will be triggered right before Searchbar instance will be destroyed |
App and Searchbar Instance Events
Searchbar instance emits events on both self instance and app instance. App instance events has same names prefixed with searchbar
.
Event | Target | Arguments | Description |
---|---|---|---|
search | searchbar | (searchbar, query, previousQuery) | Event will be triggered during search (search field change). As an argument event handler receives searchbar instance, current query and previous query |
searchbarSearch | app | ||
clear | searchbar | (searchbar, previousQuery) | Event will be triggered when user clicks on Searchbar’s “clear” element . As an argument event handler receives searchbar instance and previous (before clear) query |
searchbarClear | app | ||
enable | searchbar | (searchbar) | Event will be triggered when Searchbar becomes active/enabled. As an argument event handler receives searchbar instance |
searchbarEnable | app | ||
disable | searchbar | (searchbar) | Event will be triggered when Searchbar becomes inactive/disabled. As an argument event handler receives searchbar instance |
searchbarDisable | app | ||
beforeDestroy | searchbar | (searchbar) | Event will be triggered right before Searchbar instance will be destroyed |
searchbarBeforeDestroy | app |
Searchbar Auto Initialization
If you don’t need to use Searchbar API and your Searchbar is inside of the page and presented in DOM on moment of page initialization then it can be auto initialized with just adding additional searchbar-init
class to searchbar element, and all required parameters can be passed using data-
attributes:
<div class="page">
<div class="navbar">...</div>
<div class="page-content">
<div class="searchbar-backdrop"></div>
<!-- Searchbar with "searchbar-init" class for auto initialization and searchContainer, searchIn parameters passed in data- attributes -->
<form class="searchbar searchbar-init" data-search-container=".search-here">
...
</form>
<div class="list simple-list search-list searchbar-found">
<ul>
<li>Hulk</li>
<li>Batman</li>
<li>Superman</li>
...
</ul>
</div>
...
</div>
</div>
Parameters that used in camelCase, for example searchContainer, in data- attributes should be used in kebab-case as data-search-container
CSS Variables
Below is the list of related CSS variables (CSS custom properties).
Note that commented variables are not specified by default and their values is what they fallback to in this case.
:root {
/*
--f7-searchbar-link-color: var(--f7-bars-link-color);
--f7-searchbar-inline-input-font-size: var(--f7-searchbar-input-font-size);
--f7-searchbar-inline-input-height: var(--f7-searchbar-input-height);
*/
--f7-searchbar-input-border-width: 0px;
--f7-searchbar-input-border-color: transparent;
--f7-searchbar-input-text-color: #000;
--f7-searchbar-placeholder-color: rgba(0, 0, 0, 0.4);
}
:root .theme-dark,
:root.theme-dark {
--f7-searchbar-input-text-color: #fff;
--f7-searchbar-placeholder-color: rgba(255, 255, 255, 0.4);
}
.ios {
/*
--f7-searchbar-bg-image: var(--f7-bars-bg-image);
--f7-searchbar-bg-color: var(--f7-bars-bg-color);
--f7-searchbar-bg-color-rgb: var(--f7-bars-bg-color-rgb);
--f7-searchbar-border-color: var(--f7-bars-border-color);
*/
--f7-searchbar-height: 44px;
--f7-searchbar-inner-padding-left: 8px;
--f7-searchbar-inner-padding-right: 8px;
/*
--f7-searchbar-link-color: var(--f7-bars-link-color, var(--f7-theme-color));
*/
--f7-searchbar-input-font-size: 17px;
--f7-searchbar-input-border-radius: 8px;
--f7-searchbar-input-height: 32px;
--f7-searchbar-input-padding-horizontal: 28px;
/*
--f7-searchbar-inline-input-padding-horizontal: var(--f7-searchbar-input-padding-horizontal);
--f7-searchbar-input-clear-button-color: var(--f7-input-clear-button-color);
*/
--f7-searchbar-backdrop-bg-color: rgba(0, 0, 0, 0.4);
--f7-searchbar-shadow-image: none;
--f7-searchbar-in-page-content-margin: 0px;
--f7-searchbar-in-page-content-box-shadow: none;
--f7-searchbar-in-page-content-border-radius: 0;
--f7-searchbar-in-page-content-input-border-radius: 0;
--f7-searchbar-search-icon-color: rgba(0, 0, 0, 0.4);
--f7-searchbar-input-bg-color: #e4e4e4;
}
.ios .theme-dark,
.ios.theme-dark {
--f7-searchbar-search-icon-color: rgba(255, 255, 255, 0.4);
--f7-searchbar-input-bg-color: #2a2a2a;
}
.md {
--f7-searchbar-border-color: transparent;
--f7-searchbar-height: 48px;
--f7-searchbar-inner-padding-left: 0px;
--f7-searchbar-inner-padding-right: 0px;
--f7-searchbar-link-color: #737373;
--f7-searchbar-search-icon-color: #737373;
--f7-searchbar-input-font-size: 20px;
--f7-searchbar-input-border-radius: 0px;
--f7-searchbar-input-height: 100%;
--f7-searchbar-input-padding-horizontal: 48px;
--f7-searchbar-inline-input-padding-horizontal: 24px;
--f7-searchbar-input-clear-button-color: #737373;
--f7-searchbar-backdrop-bg-color: rgba(0, 0, 0, 0.25);
--f7-searchbar-shadow-image: var(--f7-bars-shadow-bottom-image);
--f7-searchbar-in-page-content-margin: 8px;
--f7-searchbar-in-page-content-box-shadow: var(--f7-elevation-1);
--f7-searchbar-in-page-content-border-radius: 4px;
--f7-searchbar-in-page-content-input-border-radius: 4px;
--f7-searchbar-bg-color: #fff;
--f7-searchbar-input-bg-color: #fff;
}
.md .theme-dark,
.md.theme-dark {
--f7-searchbar-bg-color: #202020;
--f7-searchbar-input-bg-color: #202020;
}
.aurora {
/*
--f7-searchbar-bg-image: var(--f7-bars-bg-image);
--f7-searchbar-bg-color: var(--f7-bars-bg-color);
--f7-searchbar-border-color: var(--f7-bars-border-color);
*/
--f7-searchbar-height: 38px;
--f7-searchbar-inner-padding-left: 8px;
--f7-searchbar-inner-padding-right: 8px;
/*
--f7-searchbar-link-color: var(--f7-bars-link-color, var(--f7-theme-color));
*/
--f7-searchbar-input-font-size: 13px;
--f7-searchbar-input-border-radius: 4px;
--f7-searchbar-input-height: 24px;
--f7-searchbar-input-padding-horizontal: 24px;
/*
--f7-searchbar-inline-input-padding-horizontal: var(--f7-searchbar-input-padding-horizontal;
--f7-searchbar-input-clear-button-color: var(--f7-input-clear-button-color);
*/
--f7-searchbar-backdrop-bg-color: rgba(0, 0, 0, 0.4);
--f7-searchbar-shadow-image: none;
--f7-searchbar-in-page-content-margin: 0px;
--f7-searchbar-in-page-content-box-shadow: none;
--f7-searchbar-in-page-content-border-radius: 0;
/*
--f7-searchbar-in-page-content-input-border-radius: var(--f7-searchbar-input-border-radius);
*/
--f7-searchbar-search-icon-color: rgba(0, 0, 0, 0.4);
--f7-searchbar-input-bg-color: #fff;
}
.aurora .theme-dark,
.aurora.theme-dark {
--f7-searchbar-input-bg-color: #333;
--f7-searchbar-search-icon-color: rgba(255, 255, 255, 0.4);
}
Example
<div class="page">
<div class="navbar">
<div class="navbar-bg"></div>
<div class="navbar-inner">
<div class="title">Search Bar</div>
<div class="subnavbar">
<!-- Searchbar with auto init -->
<form class="searchbar">
<div class="searchbar-inner">
<div class="searchbar-input-wrap">
<input type="search" placeholder="Search">
<i class="searchbar-icon"></i>
<span class="input-clear-button"></span>
</div>
<span class="searchbar-disable-button if-not-aurora">Cancel</span>
</div>
</form>
</div>
</div>
</div>
<div class="page-content">
<!-- Searchbar backdrop -->
<div class="searchbar-backdrop"></div>
<!-- hide-on-search element -->
<div class="block searchbar-hide-on-search">
<p>This block will be hidden on search. Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
</div>
<!-- search target list -->
<div class="list searchbar-found">
<ul>
<li class="item-content">
<div class="item-inner">
<div class="item-title">Acura</div>
</div>
</li>
<li class="item-content">
<div class="item-inner">
<div class="item-title">Audi</div>
</div>
</li>
<li class="item-content">
<div class="item-inner">
<div class="item-title">BMW</div>
</div>
</li>
...
<li class="item-content">
<div class="item-inner">
<div class="item-title">Volvo</div>
</div>
</li>
</ul>
</div>
<!-- Nothing found message -->
<div class="block searchbar-not-found">
<div class="block-inner">Nothing found</div>
</div>
</div>
</div>
var app = new Framework7();
// create searchbar
var searchbar = app.searchbar.create({
el: '.searchbar',
searchContainer: '.list',
searchIn: '.item-title',
on: {
search(sb, query, previousQuery) {
console.log(query, previousQuery);
}
}
});