This document describes all the options you can use to configure the Doofinder Fullscreen layer in your website.
Basics
The Doofinder script that you include in your website works just fine out of the box, but its behavior is customizable with a handful of options for almost every corner case you can imagine.
Doofinder script options comes for every possible taste, from basic knowledge about dimensions and positioning to javascript ninja, so don’t worry if a few options seem somehow obscure to you. We just hope you find what is suitable for your needs, whatever javascript-ninja-level you’re in.
If you’re here, you probably already have a layer script for your website
If that’s not the case, the easiest way to get it is from the Doofinder Admin. Choose the proper search engine and go to Configuration > Installation Scripts > Doofinder Layer
and follow the instructions.
If you want to create your own script manually, you will find more details at the end of this document, in the Standalone Script section.
The Options Array
The layer script is in charge of requiring the Javascript code to run the layer from our CDN and configuring the layer or layers described in the options array.
In your script you can see something like this
var dfFullscreenLayers = [{
toggleInput: "#query",
hashid: '1955a94db43999fcc211f925fc85f12c',
zone: 'eu1',
}];
dfFullscreenLayers
is the name we gave to the Javascript array (a list) which contains all the layer descriptions for this type of layer.
Each layer description is a Javascript object (a key-value dictionary) with option names as keys and the corresponding values assigned to them.
This means that you could have more than one layer in your website:
var dfFullscreenLayers = [
{
toggleInput: "#query",
hashid: '1955a94db43999fcc211f925fc85f12c',
zone: 'eu1'
},
{
toggleInput: "#query2",
hashid: '43999fcc85f12c1955a94dbc211f925f',
zone: 'eu1'
}
];
To customize your layer(s) you will have to add more keys to the proper layer description, taking care of commas, quotation marks for text, curly braces…:
var dfFullscreenLayers = [
{
toggleInput: "#query",
hashid: '1955a94db43999fcc211f925fc85f12c',
zone: 'eu1', // note we've added a comma
searchParams: { // to add a new option
rpp: 50, // this also needs a comma
transformer: null // but no comma here…
} // nor here…
},
{
toggleInput: "#query2",
hashid: '43999fcc85f12c1955a94dbc211f925f',
zone: 'eu1', // no comma in the last option
}
];
In order to make things simpler, we will represent single layer options in the rest of this document by omitting the dfFullscreenLayers
array so you’ll see only the layer options:
{
toggleInput: "#query",
hashid: '1955a94db43999fcc211f925fc85f12c',
zone: 'eu1'
}
Mandatory options
hashid
Identifies your search engine in our servers. You will find all possible hashid
values in the list of search engines in the Doofinder Admin.
{
hashid: 'ce2c1ex5369d3r28419bzdee7bcfaa5c'
}
zone
Geographical location assigned to your search engine. All search engines in your account have the same location.
Current possible values are:
eu1
us1
This value is automatically added by the layer installer in the Doofinder Admin.
{
zone: 'eu1'
}
toggleInput
The CSS selector of the element in your page that will open the search layer. This will usually point to the text box used to search on your website. But it could point to any other element, like a link.
The best value for this option is a CSS id, which should be unique and only used once in the HTML of your page. Everytime a user clicks on it, a FullScreen layer with a searchbox and results list will overlay your page.
{
toggleInput: '#query_input_id' // a unique CSS id
}
NOTICE: If you use too generic selectors the layer will attach to all of the matching elements. Use the layer installer from the Doofinder Admin if you don’t know how to set this value.
Use generic selectors when there’s no other way to match your text box or you want to explicitly attach the layer to more than one text box.
{
toggleInput: 'input[type="search"]' // generic selector
}
General Options
autoHideVirtualKeyboard
This option is experimental and is disabled by default. You can configure a delay in ms to auto-hide Android’s virtual keyboard when the user stops typing.
The recommended value in case you want to use this feature would be an integer greater or equal than 2000
(2s).
{
autoHideVirtualKeyboard: 2000
}
WARNING: This option may cause important usability concerns. Use it at your own risk.
callbacks
Callbacks are functions that will be called at the end of certain actions or events. They are useful to change or add some extra behavior to the layer.
The callbacks
option is an object (dictionary) which contains functions as values for specific keys.
resultsReceived
This callback will be called each time a search response is received.
{
callbacks: {
/**
* @param {Object} response Object that contains the search response.
* Use your browser dev tools to inspect it.
*/
resultsReceived: function(response) {
console.log(response);
}
}
}
hit
This function will be called each time a search result is clicked.
{
callbacks: {
/**
* @param {Node} item The DOM node that represents the item.
*/
hit: function(item) {
// item.dfClicked `true` if the item was already clicked
// item.getAttribute('href') returns the URL if the item is a link
}
}
}
loaded
This function will be called when the layer is loaded. Use it to configure any additional behavior that requires that the layer exists in the page.
{
callbacks: {
/**
* @param {Object} instance that holds the layer and its options.
*/
loaded: function(instance) {
// instance.layerOptions can be changed
// instance.configure() re-configures the layer
//
// instance.layer the layer instance itself
// instance.layer.layer the layer in the DOM
}
}
}
suggestionHit
This function will be called each time a suggestion term is clicked.
{
callbacks: {
/**
* @param {String} suggestionText Text of the clicked suggestion
*/
suggestionHit: function(suggestionText) {
// your code
}
}
}
captureForm
Captures the submit
event of the form that contains the search box. This is useful if you have any kind of icons that submit the search form; this way you can add them the same behavior as in the searchbox when you press the ENTER
key.
This option is disabled by default.
WARNING: If your page uses a single form as entry point to the whole application (usually ASP forms), don’t enable this option or the behavior of the page will break.
{
redirections: {
captureForm: false // set to `true` to enable
}
}
If no parent form relative to the searchbox is found, the layer will fall back to the default behavior (capturing the ENTER
key press).
googleAnalytics
The layer can send search events to your Google Analytics account. This option manages how search-related events are sent or if this feature must be disabled.
This option may take different forms:
- Boolean: The easy way. Just
true
orfalse
.true
: This is the default value. The layer searches for any available Google Analytics tracker in your site and uses it to send search events. If you have more than one tracker in your site or you use a custom tracker name that can’t be detected by the layer, this is not the way to go.false
: If you want to disable Google Analytics for the layer then use this.
- String: This way you can specify a Google Analytics Account ID or a custom tracker name.
- Account ID: A Google Analytics account id, like UA-XXXX-. An ad-hoc tracker will be created to send events to the specified account.
- Custom Tracker Name: This is useful when you want to use a specific tracker because there is more than one Google Analytics tracker in the page.
- Options Object: This gives more control on the way the layer works with Google Analytics. Currently you may set any of two options:
account
: This accepts a Google Analytics Account ID or a tracker name. See String above.trackPageView
: A boolean value,false
by default. Iftrue
then the layer will send search events as page views with aquery
parameter with the search terms so you can [configure Site Search]. This is independent of the events being tracked by default.
// Boolean
{
googleAnalytics: true // or false
}
// String: Account ID
{
googleAnalytics: 'UA-XXXXXXX-1'
}
// String: Tracker Name
{
googleAnalytics: 'myTracker'
}
// Object
{
googleAnalytics: {
account: 'UA-XXXXXXX-1',
trackPageView: true
}
}
To learn more about how Google Analytics works in Doofinder layers take a look at this article.
mainContainerId
You can define the prefix of the id
attribute of the layer. When multiple layers of the same type are in the same page, a sequential number is added to the default prefix for the second, third and so on.
If you want a different prefix for your layer you can set it yourself:
{
mainContainerId: 'my-first-layer'
}
redirections
Search results contain any redirection defined for the current search terms. If the user presses the ENTER
key in the search box, she will be redirected to the URL specified from the response.
To disable redirections just set this option to false
:
{
redirections: false
}
If your searchbox is located inside a form you can configure redirections to capture the form’s submit
event. Continue reading.
searchParams
This option is an object (dictionary) of parameters and values to be sent in the query string of each search request.
{
searchParams: {
paramName: 'paramValue'
}
}
All valid parameters can be found in the [Search API] reference but you will find the most common in the [Advanced Concepts] section of this document.
showInMobile
Instructs doofinder whether to force the desktop version of the layer in mobile phones.
This option is disabled by default.
{
showInMobile: false // set to `true` to enable
}
WARNING: You need the mobile add-on to use Doofinder in mobile devices.
typingStopDelay
Use this option to configure the delay in ms between when the user stops typing and the event is triggered. The default value is 1000
(1s).
It is strongly recommended not to use a value less than 1000
(1s).
{
typingStopDelay: 1000
}
WARNING: This option may cause important usability concerns. Use it at your own risk.
urlHash
The layer stores its status in the hash part of the URL. If you don’t want to generate it, set this option to false.
This option is enabled by default.
{
urlHash: true // set to `false` to disable
}
Display Options
Internationalization
lang
Language to use in the layer. The layer includes translations for some languages.
The default value for this option is en
.
{
display: {
lang: 'en' // en, es, de, fr, it
}
}
translations
The layer contains some pre-defined texts and translations for some languages. If your language is not included in the list of supported languages, you want to overwrite translations, or you want to add new ones, this is your option.
You need to provide an object (dictionary) to map the original text (the default english version) with its translated counterpart.
WARNING: Key sentences must be provided exactly as shown in the example. Otherwise they won’t work.
{
display: {
translations: {
'Results': '…',
'Search…': '…',
'Sorry, no results found.': '…',
'View less…': '…',
'View more…': '…',
'Selected Filters': '…',
'CLOSE': '…',
'CLEAR': '…',
'FILTER': '…',
'Query Too Large': '…',
'Latest Searches': '…',
'Sort by': '…',
'Relevance': '…',
'Delete': '…',
'POPULAR SUGGESTIONS': '…',
'SEARCH RESULTS': '…',
'View all {{total}} results': '…',
'Previous': '…',
'Next': '…',
'Selected Filters': '…',
'Clear all': '…',
'Suggestions:': '…',
'Did you mean:': '…'
}
}
}
currency
This is an object defining how you want prices be formatted. It has 5 attributes:
- symbol: this is the symbol you want to use for your currency, it can be either an utf-8 symbol, like ‘€’ or the html escaped sequence, like ‘€’
- decimal: The symbol used to separate the decimal part of the price. Usually ‘,’ or ‘.’.
- thousand: The symbol used to separate thousands in the price. Usually ‘.’ or ‘,’.
- precision: How many decimals you want your price to have.
- format: Where to put the currency symbol in relation with the price value. It is a format string: (“%s %v”) where %s is changed by the currency symbol and %v is changed by the price value. Say you have a price of 13 euros. Then if format is: “%s%v” the price would be shown as €13.
- forceDecimals: true by default, forces precision also for integer values.
Say you have this currency option defined:
{
display: {
currency: {
symbol: '£',
decimal: ',',
thousand: '.',
precision: 2,
format: '%s%v'
}
}
}
So a price of 13211.889 would be displayed as £13.211,89 and a price of 13211 would be displayed as £13.211,00.
NOTICE: By default the layer takes this configuration from the Doofinder servers based on the details provided for the search engine.
If you want to disable decimal formatting for integer values, disable forceDecimals
:
{
display: {
currency: {
symbol: '£',
decimal: ',',
thousand: '.',
precision: 2,
format: '%s%v',
forceDecimals: false // this changed the default value!
}
}
}
So a price of 13211 would be displayed as £13.211.
Input Behavior
captureLength
Minimum number of characters a user must type in the search box for a search request to be triggered.
The default value for this option is 3
.
{
display: {
captureLength: 3
}
}
wait
Input checking is delayed so the user has a chance of typing more characters without immediately sending search requests. You can configure the delay in milliseconds using this option.
The default value for this option is 42
.
{
display: {
wait: 42 // the meaning of life
}
}
initialSearch
When you open the fullscreen layer it’s empty by default. If you set this option to true
then the most searched items will be shown by default. Furthermore, you can specify a search string so an initial Search is done with this terms.
{
display: {
initialSearch: true // or 'men shoes' to show a default initial search
}
}
Close Behavior
closeOnEscKey
This option makes the layer close if the user presses the ESC key.
This options is enabled by default.
{
display: {
closeOnEscKey: true
}
}
Templating
templateFunctions
This option allows you to define your own template functions. Template functions transform the text passed to it so you can decide what to render in the HTML code.
Here is an example defining myBold
which simply wraps the text with the <b>
html tags.
{
display: {
templateFunctions: {
// my helper is a function that returns a function
myBold: function() {
// the returned function receives the text and
// a render function as an argument
return function(text, render) {
// you can transform the text before or after
// rendering it
return '<b>' + render(text) + '</b>';
}
}
}
}
}
Now you could use it in a custom template:
{{#results}}<h1>{{#myBold}}{{title}}{{/myBold}}</h1>{{/results}}
Take a look at the Mustache documentation to get familiar with the use of this functions and their possibilities.
templateVars
This option allows you to define your own variables to be passed to templates.
{
display: {
templateVars: {
userName: "Charles Xavier"
}
}
}
template
A template defined here overrides the skeleton of the entire Layer. All other templates are inserted somewhere inside this one. You can use it as a starting point to build your own custom layer.
WARNING: Be Careful, changing objects ids may break your layer. Do not use a custom template if you don’t know what you are doing.
NOTICE: You may feel more comfortable if you put the template code in a separate script and then import the template inside the layer options through its id.
Take a look at the Mustache documentation to get familiar with the use of templates.
Writing the layer template as Javascript code is prone to errors. The best approach is to wrap the layer template in a <script>
tag with a custom type so the browser doesn’t try to parse it as Javascript.
<script type="text/x-mustache-template" id="df-layer-template">
<!-- Your HTML/Mustache code goes here -->
</script>
Now you can reference it as any other HTML element in your page. Just make sure the layer template is defined before the layer configuration.
{
display: {
template: document.getElementById('df-layer-template').innerHTML
}
}
This is the default template:
<div class="df-fullscreen" id="{{ mainContainerId }}" hidden>
<div class="df-topbar" id="df-topbar__{{ mainContainerId }}">
{{#showTopbar}}
<div class="df-topbar__content">
{{#topbarLogo}}
<a class="df-topbar__logo" href="{{#topbarLogoLink}}{{.}}{{/topbarLogoLink}}">
<img src="{{.}}" />
</a>
{{/topbarLogo}}
<div class="df-searchbox">
<input id="df-searchbox__{{ mainContainerId }}" type="text" placeholder="{{#translate}}{{ placeholderText }}{{/translate}}">
</div>
<a class="df-icon df-icon--close" href="#" data-role="close">
<svg fill="#000000" height="42" viewBox="0 0 24 24" width="42" xmlns="http://www.w3.org/2000/svg">
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>
<path d="M0 0h24v24H0z" fill="none"/>
</svg>
</a>
</div>
{{/showTopbar}}
<div class="df-suggestions-list" id="df-suggestions__{{ mainContainerId }}" data-role="suggestion-list" hidden></div>
{{#showHeader}}
<div class="df-header" id="df-header__{{ mainContainerId }}"></div>
{{/showHeader}}
</div>
<div class="df-layer__content">
<div class="df-aside" data-role="aside">
<div class="df-aside__content" id="df-aside__{{ mainContainerId }}"></div>
</div>
<div class="df-results" id="df-results__wrapper__{{ mainContainerId }}" data-role="result-list"></div>
</div>
<div class="df-branding">
<a class="doofinderLogo" href="http://www.doofinder.com/?mktcod=REF1&utm_source=referrals&utm_medium=REF1" target="_blank">Powered by
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 284.333 76.333" xml:space="preserve" width="80" height="30">
<g>
<path class="doofinder-logo__doo" fill="#16406E" d="M38.807,40.114c-0.44,2.52-0.76,4.75-0.96,6.69c-0.201,1.94-0.3,3.45-0.3,4.53c0,0.441,0,0.81,0,1.11
c0,0.3,0.02,0.63,0.06,0.99c-1.32,0.24-2.621,0.36-3.9,0.36c-1.121,0-2.361-0.12-3.72-0.36c-0.081-0.319-0.16-0.699-0.24-1.14
c-0.081-0.44-0.12-1.1-0.12-1.98c0-0.36,0.009-0.78,0.03-1.26c0.02-0.48,0.069-0.979,0.15-1.5c-0.561,0.92-1.23,1.791-2.01,2.61
c-0.78,0.82-1.641,1.53-2.58,2.13c-0.94,0.6-1.95,1.08-3.03,1.44c-1.08,0.36-2.22,0.54-3.42,0.54c-2.64,0-4.62-0.84-5.94-2.52
c-1.32-1.68-1.98-3.9-1.98-6.66c0-3,0.45-5.9,1.35-8.7c0.9-2.799,2.24-5.28,4.02-7.44c1.779-2.16,3.99-3.89,6.63-5.19
c2.64-1.299,5.72-1.95,9.24-1.95c0.279,0,0.549,0.011,0.81,0.03c0.26,0.021,0.489,0.03,0.69,0.03c0.439-2.359,0.75-4.359,0.93-6
c0.18-1.64,0.27-3,0.27-4.08c0-0.44-0.01-0.81-0.03-1.11c-0.021-0.3-0.051-0.63-0.09-0.99c0.68-0.12,1.459-0.21,2.34-0.27
c0.879-0.06,1.64-0.09,2.28-0.09c1.16,0,2.439,0.12,3.84,0.36c0.2,0.6,0.3,1.36,0.3,2.28c0,1.761-0.24,3.9-0.72,6.42L38.807,40.114
z M32.387,28.954c-0.36-0.08-0.71-0.129-1.05-0.15c-0.34-0.02-0.67-0.03-0.99-0.03c-1.92,0-3.55,0.48-4.89,1.44
c-1.341,0.96-2.451,2.16-3.33,3.6c-0.88,1.44-1.521,2.991-1.92,4.65c-0.4,1.66-0.6,3.17-0.6,4.53c0,2.96,0.979,4.44,2.94,4.44
c1.92,0,3.699-1.17,5.34-3.51c1.64-2.34,2.84-5.63,3.6-9.87L32.387,28.954z"></path>
<path class="doofinder-logo__doo" fill="#16406E" d="M56.587,54.274c-4.121,0-7.15-1.08-9.09-3.24c-1.94-2.16-2.91-5.12-2.91-8.88c0-2.4,0.36-4.81,1.08-7.23
c0.72-2.42,1.8-4.6,3.24-6.54c1.44-1.94,3.25-3.52,5.43-4.74c2.18-1.22,4.729-1.83,7.65-1.83c4.16,0,7.209,1.101,9.15,3.3
c1.94,2.2,2.91,5.181,2.91,8.94c0,2.48-0.351,4.92-1.05,7.32c-0.7,2.4-1.77,4.56-3.21,6.48c-1.44,1.92-3.261,3.471-5.46,4.65
C62.126,53.683,59.546,54.274,56.587,54.274z M57.367,47.794c1.52,0,2.799-0.48,3.84-1.44c1.04-0.96,1.89-2.149,2.55-3.57
c0.66-1.419,1.129-2.919,1.41-4.5c0.28-1.58,0.42-3.009,0.42-4.29c0-3.68-1.5-5.52-4.5-5.52c-1.521,0-2.781,0.5-3.78,1.5
c-1,1-1.82,2.22-2.46,3.66c-0.64,1.44-1.09,2.96-1.35,4.56c-0.26,1.6-0.39,3.021-0.39,4.26
C53.107,46.014,54.526,47.794,57.367,47.794z"></path>
<path class="doofinder-logo__doo" fill="#16406E" d="M90.067,54.274c-4.121,0-7.15-1.08-9.09-3.24c-1.94-2.16-2.91-5.12-2.91-8.88c0-2.4,0.36-4.81,1.08-7.23
c0.72-2.42,1.8-4.6,3.24-6.54c1.44-1.94,3.25-3.52,5.43-4.74c2.18-1.22,4.729-1.83,7.65-1.83c4.16,0,7.209,1.101,9.15,3.3
c1.94,2.2,2.91,5.181,2.91,8.94c0,2.48-0.351,4.92-1.05,7.32c-0.7,2.4-1.77,4.56-3.21,6.48c-1.44,1.92-3.261,3.471-5.46,4.65
C95.606,53.683,93.026,54.274,90.067,54.274z M90.847,47.794c1.52,0,2.799-0.48,3.84-1.44c1.04-0.96,1.89-2.149,2.55-3.57
c0.66-1.419,1.129-2.919,1.41-4.5c0.28-1.58,0.42-3.009,0.42-4.29c0-3.68-1.5-5.52-4.5-5.52c-1.521,0-2.781,0.5-3.78,1.5
c-1,1-1.82,2.22-2.46,3.66c-0.64,1.44-1.09,2.96-1.35,4.56c-0.26,1.6-0.39,3.021-0.39,4.26
C86.587,46.014,88.006,47.794,90.847,47.794z"></path>
<g>
<path class="doofinder-logo__finder" fill="#FF7B29" d="M116.406,29.015h-4.98c0-1.08,0.08-2.139,0.24-3.18c0.16-1.04,0.459-2.139,0.9-3.3h4.98l0.12-0.48
c0.8-4.479,2.34-7.779,4.62-9.9c2.28-2.12,5.3-3.18,9.06-3.18c1.16,0,2.19,0.06,3.09,0.18c0.9,0.12,1.81,0.32,2.73,0.6
c-0.28,1.32-0.6,2.5-0.96,3.54c-0.36,1.041-0.82,2.08-1.38,3.12c-0.521-0.159-1.041-0.29-1.56-0.39c-0.52-0.1-1.08-0.15-1.68-0.15
c-0.72,0-1.371,0.09-1.95,0.27c-0.581,0.18-1.101,0.49-1.56,0.93c-0.46,0.44-0.86,1.06-1.2,1.86c-0.34,0.801-0.63,1.821-0.87,3.06
l-0.12,0.54h6.54c0,1.161-0.081,2.23-0.24,3.21c-0.16,0.98-0.46,2.07-0.9,3.27h-6.54l-4.32,24.24
c-0.521,2.919-1.23,5.34-2.13,7.26c-0.9,1.92-1.95,3.45-3.15,4.59c-1.2,1.14-2.56,1.94-4.08,2.4
c-1.521,0.459-3.161,0.69-4.92,0.69c-1.839,0-3.66-0.28-5.46-0.84c0.201-2.4,0.861-4.56,1.98-6.48c0.441,0.16,0.93,0.29,1.47,0.39
c0.54,0.1,0.97,0.15,1.29,0.15c0.76,0,1.479-0.11,2.16-0.33c0.68-0.22,1.31-0.66,1.89-1.32c0.58-0.66,1.1-1.57,1.56-2.73
c0.459-1.161,0.85-2.68,1.17-4.56L116.406,29.015z"></path>
</g>
<path class="doofinder-logo__finder" fill="#FF7B29" d="M139.667,29.014h-3.78c0-0.12-0.01-0.24-0.03-0.36c-0.021-0.12-0.03-0.26-0.03-0.42
c0-1.04,0.1-2.01,0.3-2.91c0.2-0.9,0.5-1.83,0.9-2.79h12.12l-5.46,31.02c-1.521,0.24-2.961,0.36-4.32,0.36
c-1.24,0-2.58-0.12-4.02-0.36L139.667,29.014z"></path>
<path class="doofinder-logo__finder" fill="#FF7B29" d="M154.867,35.854c0.439-2.52,0.77-4.749,0.99-6.69c0.22-1.939,0.33-3.45,0.33-4.53c0-0.44,0-0.81,0-1.11
c0-0.3-0.021-0.63-0.06-0.99c1.32-0.24,2.64-0.36,3.96-0.36c0.6,0,1.2,0.03,1.8,0.09s1.239,0.15,1.92,0.27
c0.08,0.321,0.159,0.7,0.24,1.14c0.08,0.44,0.12,1.101,0.12,1.98c0,0.36-0.01,0.72-0.03,1.08c-0.021,0.36-0.07,0.8-0.15,1.32
c0.48-0.84,1.08-1.64,1.8-2.4c0.72-0.759,1.54-1.419,2.46-1.98c0.92-0.56,1.91-1,2.97-1.32c1.059-0.319,2.13-0.48,3.21-0.48
c2.4,0,4.269,0.61,5.61,1.83c1.34,1.221,2.01,3.25,2.01,6.09c0,0.6-0.04,1.24-0.12,1.92c-0.081,0.681-0.18,1.4-0.3,2.16
l-3.48,19.68c-1.521,0.24-2.98,0.36-4.38,0.36c-1.401,0-2.781-0.12-4.14-0.36l3.36-19.02c0.159-0.8,0.24-1.56,0.24-2.28
c0-1.2-0.261-2.04-0.78-2.52c-0.521-0.48-1.26-0.72-2.22-0.72c-0.561,0-1.19,0.141-1.89,0.42c-0.7,0.28-1.41,0.87-2.13,1.77
c-0.72,0.9-1.42,2.17-2.1,3.81c-0.681,1.641-1.26,3.801-1.74,6.48l-2.22,12.06c-1.56,0.24-3.021,0.36-4.38,0.36
c-1.401,0-2.781-0.12-4.14-0.36L154.867,35.854z"></path>
<path class="doofinder-logo__finder" fill="#FF7B29" d="M214.627,40.114c-0.441,2.52-0.762,4.75-0.961,6.69c-0.201,1.94-0.301,3.45-0.301,4.53
c0,0.441,0,0.81,0,1.11c0,0.3,0.021,0.63,0.061,0.99c-1.32,0.24-2.619,0.36-3.9,0.36c-1.119,0-2.359-0.12-3.719-0.36
c-0.081-0.319-0.16-0.699-0.24-1.14c-0.081-0.44-0.12-1.1-0.12-1.98c0-0.36,0.009-0.78,0.03-1.26c0.02-0.48,0.069-0.979,0.15-1.5
c-0.561,0.92-1.23,1.791-2.01,2.61c-0.78,0.82-1.641,1.53-2.58,2.13c-0.94,0.6-1.95,1.08-3.03,1.44c-1.08,0.36-2.22,0.54-3.42,0.54
c-2.64,0-4.62-0.84-5.94-2.52c-1.32-1.68-1.98-3.9-1.98-6.66c0-3,0.45-5.9,1.35-8.7c0.9-2.799,2.24-5.28,4.02-7.44
c1.779-2.16,3.99-3.89,6.63-5.19c2.64-1.299,5.72-1.95,9.24-1.95c0.279,0,0.549,0.011,0.811,0.03c0.26,0.021,0.488,0.03,0.689,0.03
c0.439-2.359,0.75-4.359,0.93-6c0.18-1.64,0.27-3,0.27-4.08c0-0.44-0.01-0.81-0.029-1.11c-0.021-0.3-0.051-0.63-0.09-0.99
c0.68-0.12,1.459-0.21,2.34-0.27c0.879-0.06,1.641-0.09,2.279-0.09c1.16,0,2.439,0.12,3.84,0.36c0.201,0.6,0.301,1.36,0.301,2.28
c0,1.761-0.24,3.9-0.721,6.42L214.627,40.114z M208.207,28.954c-0.361-0.08-0.711-0.129-1.051-0.15c-0.34-0.02-0.67-0.03-0.99-0.03
c-1.92,0-3.55,0.48-4.89,1.44c-1.341,0.96-2.451,2.16-3.33,3.6c-0.88,1.44-1.521,2.991-1.92,4.65c-0.4,1.66-0.6,3.17-0.6,4.53
c0,2.96,0.979,4.44,2.94,4.44c1.92,0,3.699-1.17,5.34-3.51c1.64-2.34,2.84-5.63,3.601-9.87L208.207,28.954z"></path>
<path class="doofinder-logo__finder" fill="#FF7B29" d="M229.686,41.794c0.24,1.92,0.88,3.351,1.92,4.29c1.04,0.94,2.56,1.41,4.561,1.41
c1.599,0,3.009-0.169,4.229-0.51c1.22-0.339,2.51-0.79,3.87-1.35c0.64,0.801,1.069,1.77,1.29,2.91c0.22,1.14,0.33,2.35,0.33,3.63
c-0.681,0.32-1.47,0.61-2.37,0.87c-0.9,0.26-1.83,0.48-2.79,0.66c-0.96,0.18-1.92,0.32-2.88,0.42c-0.96,0.1-1.82,0.15-2.58,0.15
c-2.44,0-4.53-0.3-6.271-0.9c-1.739-0.6-3.18-1.449-4.319-2.55c-1.141-1.1-1.98-2.439-2.521-4.02c-0.54-1.58-0.81-3.33-0.81-5.25
c0-2.439,0.42-4.839,1.26-7.2c0.84-2.359,2.03-4.47,3.57-6.33c1.539-1.86,3.42-3.36,5.64-4.5c2.22-1.14,4.71-1.71,7.47-1.71
c1.32,0,2.551,0.161,3.69,0.48c1.14,0.32,2.13,0.81,2.97,1.47s1.5,1.47,1.98,2.43c0.479,0.96,0.72,2.08,0.72,3.36
c0,1.8-0.42,3.36-1.26,4.68c-0.84,1.32-1.961,2.44-3.36,3.36c-1.4,0.92-2.99,1.67-4.77,2.25c-1.78,0.58-3.63,1.011-5.55,1.29
L229.686,41.794z M233.105,35.674c1.52-0.24,2.76-0.549,3.72-0.93c0.96-0.379,1.72-0.8,2.28-1.26c0.56-0.459,0.939-0.93,1.14-1.41
s0.301-0.96,0.301-1.44c0-0.759-0.251-1.38-0.75-1.86c-0.501-0.48-1.17-0.72-2.011-0.72c-1.04,0-1.99,0.23-2.85,0.69
c-0.86,0.46-1.61,1.071-2.25,1.83c-0.641,0.76-1.19,1.63-1.65,2.61c-0.46,0.981-0.81,1.971-1.05,2.97L233.105,35.674z"></path>
<path class="doofinder-logo__finder" fill="#FF7B29" d="M254.886,35.854c0.439-2.52,0.77-4.749,0.99-6.69c0.219-1.939,0.33-3.45,0.33-4.53c0-0.44,0-0.81,0-1.11
c0-0.3-0.021-0.63-0.061-0.99c1.32-0.24,2.64-0.36,3.96-0.36c0.601,0,1.2,0.03,1.8,0.09c0.601,0.06,1.239,0.15,1.92,0.27
c0.08,0.321,0.16,0.7,0.24,1.14c0.08,0.44,0.12,1.101,0.12,1.98c0,0.36-0.01,0.72-0.03,1.08c-0.021,0.36-0.07,0.8-0.149,1.32
c0.399-0.72,0.899-1.43,1.5-2.13c0.6-0.7,1.27-1.33,2.01-1.89c0.739-0.56,1.56-1.01,2.46-1.35c0.9-0.339,1.89-0.51,2.97-0.51
c0.84,0,1.561,0.1,2.16,0.3c0.039,0.16,0.061,0.321,0.061,0.48c0,0.161,0,0.34,0,0.54c0,1.121-0.141,2.28-0.42,3.48
c-0.281,1.2-0.66,2.2-1.141,3c-0.24-0.039-0.5-0.08-0.78-0.12c-0.28-0.039-0.64-0.06-1.079-0.06c-1.641,0-2.991,0.28-4.051,0.84
c-1.06,0.561-1.93,1.35-2.609,2.37c-0.681,1.02-1.221,2.25-1.62,3.69c-0.4,1.44-0.761,3.04-1.08,4.8l-2.22,12.06
c-1.561,0.24-3.021,0.36-4.381,0.36c-1.4,0-2.78-0.12-4.14-0.36L254.886,35.854z"></path>
<circle class="doofinder-logo__finder" fill="#FF7B29" cx="145.924" cy="15.034" r="4.688"></circle>
</g>
</svg>
</a>
</div>
<a class="df-icon df-in df-out" href="#" data-role="scrolltop" data-scroll-in-out>
<svg fill="#000000" height="42" viewBox="0 0 24 24" width="42" xmlns="http://www.w3.org/2000/svg">
<path d="M0 0h24v24H0V0z" fill="none"/>
<path d="M4 12l1.41 1.41L11 7.83V20h2V7.83l5.58 5.59L20 12l-8-8-8 8z"/>
</svg>
</a>
</div>
Writing the layer template as Javascript code is prone to errors. The best approach is to wrap the layer template in a <script>
tag with a custom type so the browser doesn’t try to parse it as Javascript.
<script type="text/x-mustache-template" id="df-layer-template">
<!-- Your HTML/Mustache code goes here -->
</script>
Now you can reference it as any other HTML element in your page. Just make sure the layer template is defined before the layer configuration.
{
display: {
template: document.getElementById('df-layer-template').innerHTML
}
}
wide
The wide
option allows to display the results using the full width of the screen or restrict to a fixed width. If true
(default), results will occupy all the available screen, if it’s false the layer will occupy a maximum width of 960px
.
Placement
insertionPoint
By default the layer is appended to the <body>
of your page. If you want to put the layer in a different place you can specify a CSS selector pointing to an element of your page.
Setting this option only just changes the place where the layer is appended. If you want to also change the way the layer is inserted relative to the insertion point take a look at insertionMethod.
{
display: {
insertionPoint: "#myresults"
}
}
The previous example would append the layer to an element with the provided id attribute:
<div id="myresults">
<h1>I'm a header</h1>
<!-- layer will be appended here -->
</div>
insertionMethod
This option is used in conjunction with insertionPoint
and lets you specify the way the layer is inserted in the page.
Valid values for this option are:
append
: This is the default value. The layer is appended as the last element of the specified insertion point.prepend
: Inserts the layer as the first element of the specified insertion point.before
: Inserts the layer as a sibling BEFORE the specified insertion point.after
: Inserts the layer as a sibling AFTER the specified insertion point.html
: The layer replaces the content of the specified insertion point.
NOTICE: When insertionPoint
is the <body>
, only append
and prepend
are valid methods.
Results configuration
scrollOffset
Distance in px
from the bottom of the results content. When the user reached that point scrolling the results a new results page is triggered.
The default value for this option is 500
.
{
display: {
results: {
scrollOffset: 500 // no units allowed here
}
}
}
urlParams
Object (a dictionary) with parameters to be appended to the URL of each result.
{
display: {
results: {
urlParams: {
source: 'doofinder',
'campaign-id': 123456 // some keys need to be quoted
}
}
}
}
NOTICE: This only works if you use the {{#url-params}}{{/url-params}}
function in your results template (the default template uses it).
In the previous example, this URL:
http://www.example.com/products/P1
would be converted to:
http://www.example.com/products/P1?source=doofinder&campaign-id=123456
queryParam
This option makes the search parameters being added to the urlParams
in the specified key.
{
display: {
results: {
queryParam: 'q'
}
}
}
NOTICE: This only works if you use the {{#url-params}}{{/url-params}}
function in your results template (the default template uses it).
In the previous example, this URL:
http://www.example.com/products/P1
would be converted to:
http://www.example.com/products/P1?q=whatever-you-searched
initialLayout
The way the results are displayed by default when the layer loads. This option can be grid
or list
.
{
display: {
results: {
initialLayout: 'grid'
}
}
}
Results template
You can replace the default results template by your own template by using this option.
If you need to include custom fields from your data feed, you should check also the [transformer] option to see how to receive those fields in the json response from the server.
The templates are defined using the Mustache template system.
Here is an example which defines a very simple custom template that overrides the default:
layerOptions = {
display: {
results: {
template: '{{#results}}<h1>{{title}}</h1>{{/results}}'
}
}
}
Notice: To make templating easier, you can write your custom template inside a special <script type=”text/x-mustache-template”> tag with a unique id. Then you can reference the template by id from the layer configuration script. The template must be declared before the Doofinder script.
Warning: Some templates are more sensitive to changes than others. Note that if you modify the default templates of the layer, the layer may malfunction in the future. To restore the correct operation of the layer simply deactivate the custom template in the layer options.
As you can see there are also some sections which are functions like: format-currency, remove-protocol, url-params
and translate
. You can also define your own functions with the Template Functions option.
{{#is_first}}
{{#banner}}
<div class="df-banner">
<a {{#blank}}target="_blank" rel="noopener noreferer"{{/blank}} href="{{link}}" data-role="banner" data-banner="{{id}}">
{{#image}}
<img src="{{#remove-protocol}}{{image}}{{/remove-protocol}}">
{{/image}}
{{#html_code}}
{{{html_code}}}
{{/html_code}}
</a>
</div>
{{/banner}}
{{/is_first}}
{{#total}}
{{#results}}
<div class="df-card" data-role="result">
<a class="df-card__main" href="{{#url-params}}{{{link}}}{{/url-params}}" data-role="result-link" data-dfid="{{dfid}}">
{{#image_link}}
<figure class="df-card__image">
<img src="{{#remove-protocol}}{{image_link}}{{/remove-protocol}}" alt="{{title}}">
</figure>
{{/image_link}}
<div class="df-card__content">
<div class="df-card__title">{{title}}</div>
<div class="df-card__description">{{{description}}}</div>
{{#price}}
<div class="df-card__pricing">
<span class="df-card__price {{#sale_price}}df-card__price--old{{/sale_price}}">
{{#format-currency}}{{price}}{{/format-currency}}
</span>
{{#sale_price}}
<span class="df-card__price df-card__price--new">
{{#format-currency}}{{sale_price}}{{/format-currency}}
</span>
{{/sale_price}}
</div>
{{/price}}
{{#df_rating}}
<div>
<div class="df-rating" title="{{df_rating}}">
<div class="df-rating__value" style="width: {{#rating-percent}}{{df_rating}}{{/rating-percent}}">
<i>★</i><i>★</i><i>★</i><i>★</i><i>★</i>
</div>
<div class="df-rating__placeholder">
<i>★</i><i>★</i><i>★</i><i>★</i><i>★</i>
</div>
</div>
</div>
{{/df_rating}}
</div>
</a>
</div>
{{/results}}
{{/total}}
{{^total}}
{{#noResultsHTML}}{{{noResultsHTML}}}{{/noResultsHTML}}
{{^noResultsHTML}}
<p class="df-no-results">{{#translate}}Sorry, no results found.{{/translate}}</p>
{{/noResultsHTML}}
{{/total}}
Facets configuration
Under the facets
key you can configure everything related to how filters work in the layer.
width
Setting this option overrides the width value (absolute or relative) set by CSS for the facets column.
{
display: {
facets: {
width: '20%' // relative width
}
}
}
NOTICE: You can use almost any valid CSS unit but it’s safer to use px or %. No explicit unit means px.
shownTerms
The number of terms that are visible by default for all text widgets.
{
display: {
facets: {
shownTerms: 10
}
}
}
attached
Whether you want the facets layer “attached” to the right side or the left side of the results layer.
Possible values are:
right
left
auto
The default value for this option is auto.
{
display: {
facets: {
attached: 'auto'
}
}
}
startCollapsed
If you want to display the facet panels collapsed by default just set this option to true
.
The default value for this option is false
.
{
display: {
facets: {
startCollapsed: false
}
}
}
selectedFilters
If you want to display a summary of the selected filters at the top of the facets aside, set this option to true
.
The default value for this option is false
.
{
display: {
facets: {
selectedFilters: false
}
}
}
NOTICE: This option is not available in the mobile version due to screen size limits.
custom
The custom key is very powerful. It allows you to customize facets by changing the type of widget to use to render filters and even the options of those widgets.
There are some rules to take into account with this option:
- The value of this option is an array (list) of facet configuration objects.
- You can customize the facets you defined in the Doofinder Admin but nothing else.
- If you use these options you must declare all the facets you want to display.
{
display: {
facets: {
custom: [
// Your facet definitions go here
]
}
}
}
A facet definition is an object (a dictionary). Properties of the definition may vary depending on the type of facet and the widget used to display it.
The minimal definition you can use to specify that a widget for certain facet must be added is an object with a name
property:
{
display: {
facets: {
custom: [
{name: 'brand'},
{name: 'best_price'}
]
}
}
}
In that case, the rest of the properties will be obtained from the server:
{
"facets": [
{
"name": "best_price",
"type": "range",
"label": "Best Price"
},
{
"name": "brand",
"type": "terms",
"label": "Brand"
}
]
}
Any of the properties of the facets (except the name) could be changed if needed:
{
display: {
facets: {
custom: [
{name: 'brand', label: 'Available Brands'},
{name: 'best_price'}
]
}
}
}
The type of the facet determines the widget that will render it. There are 4 types of facets you can use:
- terms: A collapsible list of terms. This is the default widget for text fields.
- color: A color selector. Useful for clothes, or other items that can be filtered by color.
- grid: A grid of terms. Useful to filter by size. Displays text terms in a compact way
- range: A slider to filter numbers. Useful for prices or other numeric fields.
This is a complete example to see the available options (less commonly used options are commented):
{
display: {
facets: {
custom: [
{
name: 'brand',
label: 'Available Brands',
type: 'terms',
shownTerms: 10,
// startCollapsed: true,
// templateVars: {
// viewMoreLabel: "View more…",
// viewLessLabel: "View less…"
// },
// templateFunctions: {},
// template: '…'
},
{
name: 'color',
label: 'Color',
type: 'color',
// map color names to real colors
// any valid CSS color can be used
colors: {
'beige': '#ffcc99',
'black': '#000000',
'blue': '#0059b3',
'brown': '#734d26',
'gold': '#cccc00',
'gray': '#666666',
'green': '#009933',
'navy blue': '#000099',
'orange': '#ff9900',
'red': '#b30000',
'white': '#ffffff',
'yellow': '#b3b300'
},
// templateVars: {},
// templateFunctions: {},
// template: '…'
},
{
name: 'size',
label: 'Size',
type: 'grid',
// you can specify all possible
// terms in a list and values
// will be ordered "as is" (any
// extra value will appear at
// the end)
order: [
'XS', 'S', 'M',
'L', 'XL', 'XXL'
],
// templateVars: {},
// templateFunctions: {},
// template: '…'
},
{
name: 'tags',
label: 'Tags',
type: 'grid',
// if you prefer you can
// just specify if you want
// terms sorted ascending or
// descending
order: 'asc', // asc | desc
// templateVars: {},
// templateFunctions: {},
// template: '…'
},
{
name: 'best_price',
label: 'Price',
type: 'range',
// you can pass a currency-like
// object to format values
numericFormat: {
symbol: '£',
decimal: '.',
thousand: ',',
precision: 2,
format: '%s%v'
},
// templateVars: {},
// templateFunctions: {},
// template: '…',
//
// you can change the scale of the slider to
// "zoom in" the range selected by users in
// case you have very low and high limits so
// they can refine the range in a proper way.
//
// zoom represents the percentage of the slider
// used to zoom the selected range.
//
// a value of `false` (default) disables zoom.
//
// zoom: 60 // min: 50, max: 90
},
{
name: 'length',
label: 'Length',
type: 'range',
// you can provide a formatting
// function directly
numericFormat: function(value){
return value.toFixed(2) + "cm";
},
// templateVars: {},
// templateFunctions: {},
// template: '…'
}
]
}
}
}
Although is not common to do it, all widgets can be customized by setting a template and you can also add additional templateVars and templateFunctions to be used in the template.
If you want to see the default template for each widget type take a look at these options, which let you customize the template for all widgets globally:
panelTemplate
Facets are rendered inside collapsible panels. You can use this option to customize the template of those panels.
Notice: To make templating easier, you can write your custom template inside a special <script type="text/x-mustache-template">
tag with a unique id. Then you can reference the template by id from the layer configuration script. The template must be declared before the Doofinder script.
Warning: Some templates are more sensitive to changes than others. Note that if you modify the default templates of the layer, the layer may malfunction in the future. To restore the correct operation of the layer simply deactivate the custom template in the layer options.
The default template for panels:
<div class="df-panel" id="{{panelElement}}"
data-role="panel" data-facet="{{name}}">
<a class="df-panel__title" id="{{labelElement}}"
data-role="panel-label" data-toggle="panel"
href="#">
{{label}}
</a>
<div class="df-panel__content" id="{{contentElement}}"
data-role="panel-content"></div>
</div>
{
display: {
facets: {
panelTemplate: document.getElementById('…').innerHTML
}
}
}
termsTemplate
You can use this option to customize the template of the terms widget.
Notice: To make templating easier, you can write your custom template inside a special <script type="text/x-mustache-template">
tag with a unique id. Then you can reference the template by id from the layer configuration script. The template must be declared before the Doofinder script.
Warning: Some templates are more sensitive to changes than others. Note that if you modify the default templates of the layer, the layer may malfunction in the future. To restore the correct operation of the layer simply deactivate the custom template in the layer options.
This is the default template for the terms widget:
{{#terms}}
<div class="df-term" data-facet="{{name}}" data-value="{{key}}"
{{#extra-content}}{{index}}{{/extra-content}}
{{#selected}}data-selected{{/selected}}>
<span class="df-term__value">{{key}}</span>
<span class="df-term__count">{{doc_count}}</span>
</div>
{{/terms}}
{{#show-more-button}}{{terms.length}}{{/show-more-button}}
{
display: {
facets: {
termsTemplate: document.getElementById('…').innerHTML
}
}
}
colorTemplate
You can use this option to customize the template of the color widget.
Notice: To make templating easier, you can write your custom template inside a special <script type="text/x-mustache-template">
tag with a unique id. Then you can reference the template by id from the layer configuration script. The template must be declared before the Doofinder script.
Warning: Some templates are more sensitive to changes than others. Note that if you modify the default templates of the layer, the layer may malfunction in the future. To restore the correct operation of the layer simply deactivate the custom template in the layer options.
This is the default template for the color widget:
<div class="df-color-list">
{{#terms}}
<div class="df-color {{^color}}df-no-color{{/color}}"
data-facet="{{name}}" data-value="{{key}}"
{{#selected}}data-selected{{/selected}}
{{#color}}style="background-color: {{color}};"{{/color}}
title="{{key}}">
{{key}}
</div>
{{/terms}}
</div>
{
display: {
facets: {
colorTemplate: document.getElementById('…').innerHTML
}
}
}
gridTemplate
You can use this option to customize the template of the grid widget.
Notice: To make templating easier, you can write your custom template inside a special <script type="text/x-mustache-template">
tag with a unique id. Then you can reference the template by id from the layer configuration script. The template must be declared before the Doofinder script.
Warning: Some templates are more sensitive to changes than others. Note that if you modify the default templates of the layer, the layer may malfunction in the future. To restore the correct operation of the layer simply deactivate the custom template in the layer options.
This is the default template for the grid widget:
<div class="df-grid">
{{#terms}}
<div class="df-grid-item" data-facet="{{name}}"
data-value="{{key}}"
{{#selected}}data-selected{{/selected}}>
{{key}}
</div>
{{/terms}}
</div>
{
display: {
facets: {
gridTemplate: document.getElementById('…').innerHTML
}
}
}
rangeTemplate
You can use this option to customize the template of the range widget.
Notice: To make templating easier, you can write your custom template inside a special <script type="text/x-mustache-template">
tag with a unique id. Then you can reference the template by id from the layer configuration script. The template must be declared before the Doofinder script.
Warning: Some templates are more sensitive to changes than others. Note that if you modify the default templates of the layer, the layer may malfunction in the future. To restore the correct operation of the layer simply deactivate the custom template in the layer options.
This is the default template for the range widget:
<div class="df-slider" data-facet="{{name}}"></div>
{
display: {
facets: {
rangeTemplate: document.getElementById('…').innerHTML
}
}
}
Header configuration
Layers come with a special header section which will be more or less complete depending on the type of layer you’re using.
The header is usually in charge of giving details like the number of results in the search response, or providing buttons for certain actions.
show
Indicates if the header must be displayed or not.
The default value for this option is true.
display: {
header: {
show: true
}
}
template
display: {
header: {
template: '…'
}
}
Notice: To make templating easier, you can write your custom template inside a special <script type="text/x-mustache-template">
tag with a unique id. Then you can reference the template by id from the layer configuration script. The template must be declared before the Doofinder script.
Warning: Some templates are more sensitive to changes than others. Note that if you modify the default templates of the layer, the layer may malfunction in the future. To restore the correct operation of the layer simply deactivate the custom template in the layer options.
The default template is:
<b>{{#translate}}Results{{/translate }}:</b>
<span data-role="total">{{ total }}</span>
Mobile Version
If you have the mobile version enabled for your search engine you can tweak some aspects of the integration.
Under the mobile key you can set or override most of the options of the layer. Most of the options available in the main layer are available for the mobile layer as well.
If you want to deactivate the mobile version for a layer just set the mobile option to false.
{
mobile: false
}
maxWidth
The maximum viewport width where the mobile version will be shown. By default 767px.
{
mobile: {
maxWidth: 767
}
}
toggleInput
If you have different search boxes for desktop and mobile, you can set the toggleInput option under the mobile key.
NOTICE: In V5 this option could be set via queryInput or toggleInput indistinctly. Since V6 the only valid option is toggleInput.
{
mobile: {
toggleInput: '#mobile_search_box'
}
}
hashid
If you want to use a different SearchEngine for your mobile version you can set a different hashid.
{
mobile: {
hashid: '1955a94db43999fcc211f925fc85f12c'
}
}
voiceSearch
Voice Search is enabled by default in compatible mobile devices. Devices that don’t support Voice Search won’t see anything special in the UI.
The default value for this options is true. If you want to disable Voice Search for all users just set this option to false.
{
mobile: {
voiceSearch: false
}
}
Display Options
You can set the display options, since the mobile layer is fullscreen, positioning options have no sense.
initialSearch
Displays the top searches when the mobile layer is opened and no query has been done.
The value of this option is true by default, unless there’s a background image defined in the templateVars.
If you want to show an empty layer, set this option to false.
{
mobile: {
display: {
initialSearch: false
}
}
}
If you want to perform a custom search just put the search terms there:
{
mobile: {
display: {
initialSearch: 'red boots'
}
}
}
closeOnHit
Closes the mobile layer when a result is clicked. This is disabled by default but you should consider using it when your site is a one-page-application that loads URLs with AJAX without changing page location.
The default value of this option is false.
{
mobile: {
display: {
closeOnHit: false
}
}
}
template
You can customize your layer template like in the desktop version but the template in this case is different:
<div class="df-mobile"{{#images.body}} style="background-image:url('{{images.body}}');"{{/images.body}} id="{{ mainContainerId }}" hidden>
<div class="df-mobile__wrapper">
<div class="df-mobile__header" id="df-mobile__header__{{ mainContainerId }}">
{{#images.header}}
<div class="df-mobile__header__image">
<img src="{{ images.header }}">
</div>
{{/images.header}}
<form action="" method="get">
<div class="df-mobile__searchbox" data-empty="true">
{{#voicesearch}}
<button type="button" data-role="voicesearch">
<svg fill="#606569" width="24" height="24" viewBox="0 0 24 24" enable-background="new 0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M12,14c1.66,0,3-1.34,3-3V5c0-1.66-1.34-3-3-3S9,3.34,9,5v6C9,12.66,10.34,14,12,14z"/>
<path d="M17,11c0,2.76-2.24,5-5,5s-5-2.24-5-5H5c0,3.53,2.61,6.43,6,6.92V21h2v-3.08c3.39-0.49,6-3.39,6-6.92H17z"/>
<path d="M0 0h24v24H0z" fill="none"/>
</svg>
</button>
{{/voicesearch}}
{{#imagesearch}}
<button type="button" data-role="imagesearch" class="fileContainer">
<svg id="df-mobile__imagesearch_icon__{{ mainContainerId }}" fill="#606569" width="24" height="24" viewBox="0 0 24 24"
enable-background="new 0 0 24 24"
xmlns="http://www.w3.org/2000/svg">
<circle cx="12" cy="12" r="3.2"/>
<path d="M9 2L7.17 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2h-3.17L15 2H9zm3 15c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5z"/>
<path d="M0 0h24v24H0z" fill="none"/>
</svg>
<svg id="df-mobile__imagesearch_loading__{{ mainContainerId }}" class="spinner" width="24px" height="24px"
viewBox="0 0 66 66" xmlns="http://www.w3.org/2000/svg">
<circle class="path" fill="none" stroke-width="6"
stroke-linecap="round" cx="33" cy="33"
r="30"></circle>
</svg>
<input data-role="image-search-control" id="df-mobile__imagesearch__{{ mainContainerId }}" type="file" accept="image/*"/>
</button>
{{/imagesearch}}
<svg class="df-mobile__searchbox__loupe" fill="#606569" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>
<path d="M0 0h24v24H0z" fill="none"/>
</svg>
<input type="search" placeholder="{{#translate}}{{placeholderText}}{{/translate}}" id="df-mobile__searchbox__{{ mainContainerId }}" autocapitalize="off" autocomplete="off" autocorrect="off">
<button type="button" data-role="clear">{{#translate}}CLEAR{{/translate}}</button>
<button type="button" data-role="close">{{#translate}}CLOSE{{/translate}}</button>
</div>
<div class="df-mobile__header__actions" id="df-mobile__header__actions__{{ mainContainerId }}"></div>
<div class="df-mobile__suggestions" id="df-mobile-suggestions__{{ mainContainerId }}" data-role="suggestion-list" hidden>
</div>
</form>
</div>
<div class="df-mobile__content" id="df-mobile__content__{{ mainContainerId }}"></div>
<button class="df-mobile__action-button df-in df-out" type="button" data-role="close" data-scroll-in-out>
<svg fill="#606569" height="48" viewBox="0 0 24 24" width="48" xmlns="http://www.w3.org/2000/svg">
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>
<path d="M0 0h24v24H0z" fill="none"/>
</svg>
</button>
<button class="df-mobile__action-button df-in df-out" type="button" data-role="scrolltop" data-scroll-in-out>
<svg fill="#606569" height="48" viewBox="0 0 24 24" width="48" xmlns="http://www.w3.org/2000/svg">
<path d="M0 0h24v24H0V0z" fill="none"/>
<path d="M4 12l1.41 1.41L11 7.83V20h2V7.83l5.58 5.59L20 12l-8-8-8 8z"/>
</svg>
</button>
</div>
<div class="df-mobile__overlay" data-role="toggle-filters"></div>
<div class="df-mobile__aside">
<div class="df-mobile__aside__actions">
<button class="df-mobile__button" type="button" data-role="toggle-filters">{{#translate}}CLOSE{{/translate}}</button>
<button class="df-mobile__button" type="button" data-role="clear-filters">{{#translate}}CLEAR{{/translate}}</button>
</div>
<div id="df-mobile__aside__sorting__{{ mainContainerId }}"></div>
<div class="df-mobile__aside__content" id="df-mobile__aside__content__{{ mainContainerId }}"></div>
</div>
</div>
Notice: To make templating easier, you can write your custom template inside a special <script type="text/x-mustache-template">
tag with a unique id. Then you can reference the template by id from the layer configuration script. The template must be declared before the Doofinder script.
Warning: Some templates are more sensitive to changes than others. Note that if you modify the default templates of the layer, the layer may malfunction in the future. To restore the correct operation of the layer simply deactivate the custom template in the layer options.
{
mobile: {
display: {
template: document.getElementById('…').innerHTML
}
}
}
templateVars
Like in the desktop version of the layer, you can set variables to be used in the template. In this case some variables are available by default:
{
mobile: {
display: {
templateVars: {
placeholderText: 'Search…',
images: {
header: null,
body: null
}
}
}
}
}
placeholderText
This is a special variable that corresponds to the text that will be used as the placeholder for the search input in the mobile layer.
images
This is a special variable / object that you can use to configure some images to adapt the look and feel of the layer:
- header: will appear before the search box.
- body: will appear as a centered background image in the layer. Using this option implies mobile.display.showMostSearched being false.
NOTICE: You’re not forced to use these values, they’re provided to avoid modifying the layer template just to add a custom header/body image. If you need a third image just add it and adapt the template to your needs.
templateFunctions
Like in the desktop version you can create your own template functions. Refer to templateFunctions for more information.
{
mobile: {
display: {
templateFunctions: {}
}
}
}
Results Configuration
template
You can set your own results template to show extra content in your results or shape the content as you want.
Refer to Results Template Configuration in the desktop version for more information.
{
mobile: {
display: {
results: {
template: document.getElementById('…').innerHTML
}
}
}
}
Facets Configuration
You can override almost any facets options from the desktop configuration for the mobile version of the layer. Refer to Facets Configuration for more details.
{
display: {
facets: {
startCollapsed: false
}
},
mobile: {
display: {
facets: {
startCollapsed: true
}
}
}
}
Advanced Concepts
Search Parameters
filter
If you want to include only results matching some condition you can use the filter parameter in your layer configuration.
See Filter Parameters in the Search API reference to learn more about filters.
{
searchParams: {
filter: {
categories: ['Awesome', 'Other'],
brand: ['My Brand'],
best_price: {
gte: 100
}
}
}
}
exclude
If you want to exclude results matching some condition you can use the exclude parameter in your layer configuration.
{
searchParams: {
exclude: {
categories: ['This not', 'Other'],
brand: ['Excluded brand']
}
}
}
sort
You can specify fields to sort results. See Sort Parameters:
{
searchParams: {
sort: [
{'_score': 'desc'},
{'price': 'asc'},
{'brand': 'desc'}
]
}
}
WARNING: In order to being able to sort by multi-word fields (like title), that field must be included into the Custom Sorting fields of the Advanced Settings of our administration panel.
type
If you want to restrict the searches to some of your data types. Just set this property:
{
searchParams: {
type: ['product', 'posts']
}
}
In the example above you will be searching just products and posts.
query_name
If you want to execute always a specific kind of query you can set this option (see query_name in Dark magic parameters):
{
searchParams: {
query_name: 'fuzzy'
}
}
min_score
The minimum score required for results to be considered valid. Results with scoring below this won’t be included in the search results.
{
searchParams: {
min_score: 0.5
}
}
transformer
Doofinder search servers return the results transformed so layers can work without too much configuration.
The default transformer is basic which populates these fields:
- title: The title of the product.
- type: This usually will be product.
- hashid: The unique identificator of your search engine.
- dfid: The doofinder id of your product.
- link: The link to your product.
- image_link: The image source of the product.
- description: The description of the product.
- price: The price of the product.
- sale_price: The sale price of the product, if any.
If you want to display any other data you’ve indexed or the original field names, first you have to set this option to null:
{
searchParams: {
transformer: null
}
}
This will make the server to return all your data when querying.
rpp
Results per page, how many results you want to be returned on each query.
{
searchParams: {
rpp: 20
}
}
The Standalone Script
The easiest way to try Doofinder is by using one of our layers. You get a snippet of text and then you just include it in the HTML of your website.
This is how the standard Doofinder script looks like:
<script>
var doofinder_script ='//cdn.doofinder.com/media/js/doofinder-fullscreen.7.latest.min.js';
(function(d,t){var f=d.createElement(t),s=d.getElementsByTagName(t)[0];f.async=1;
f.src=('https:'==location.protocol?'https:':'http:')+doofinder_script;
f.setAttribute('charset','utf-8');
s.parentNode.insertBefore(f,s)}(document,'script')
);
var dfFullscreenLayers = [{
toggleInput: '#query',
hashid: '1955a94db43999fcc211f925fc85f12c',
zone: 'eu1',
display: {
lang: 'en'
}
}];
</script>
And this is what it does:
- First of all, the URL of the layer’s source code is saved in a variable.
- Then a function is called to create a <script> tag wherever the rest of <script> tags are in your site.
- Then it declares the layers to be used in the page in the dfFullscreenLayers variable.
- All this time the <script> tag we created has been downloading the code asynchronously. When the code is ready then the layers are instantiated and configured.
But, what if I use RequireJS in my page? That would break my site… Well, let’s see that case.
RequireJS: the easy way
This is the easiest script you can use in a RequireJS environment if you only want to copy and paste a snippet with no hassle:
<script>
var dfUrl = '//cdn.doofinder.com/media/js/doofinder-fullscreen.7.latest.min.js';
(function(c,o,k,e){var r,t,i=setInterval(function(){t+=c;r=typeof(require)==='function';
if(t>=o||r)clearInterval(i);if(r)require([k],e)},c)})(100, 10000, dfUrl, function(doofinder){
doofinder.fullscreen.setLayers([{
toggleInput: '#query',
hashid: '1955a94db43999fcc211f925fc85f12c',
zone: 'eu1',
display: {
lang: 'en'
}
}]);
});
</script>
And this is what it does:
- First of all, the URL of the layer’s source code is saved in a variable.
- Then a function is called to check periodically that the require function exists in the page. The function stops if the function is not available after 10s.
- Then, the layer initialization is executed manually via setLayers.
RequireJS: the hard way
If you want to add Doofinder to your existing RequireJS workflow then you can just require its source code from a URL:
// DON'T COPY AND PASTE THIS CODE DIRECTLY INTO YOUR HTML!
// This code must be integrated into your existing RequireJS-based code.
require(['//cdn.doofinder.com/media/js/doofinder-fullscreen.7.latest.min.js'], function(doofinder){
doofinder.fullscreen.setLayers([{
toggleInput: "#query",
hashid: '1955a94db43999fcc211f925fc85f12c',
zone: 'eu1',
"display": {
"lang": 'en'
}
}]);
});
Configure the layers manually
In case you want to control when the layers are loaded, just pass the list of layers to the setLayers method. Just make sure that doofinder is completely loaded in your page.
doofinder.fullscreen.setLayers([{
toggleInput: "#query",
hashid: '1955a94db43999fcc211f925fc85f12c',
zone: 'eu1',
"display": {
"lang": 'en'
}
}]);
Change options after load
When doofinder is loaded, dfFullscreenLayers is replaced by an array of Doofinder Configuration Objects or, if run as a module on a requirejs environment, the dfFullscreenLayers array is created and made accesible at the browser’s window object. These objects can be used to change some configuration during the execution.
This could be useful, if you wanted to change the layer behavior depending on the user in session, the screen size…
So you can do this in two steps:
- Change an option in the property dfFullscreenLayers[0].layerOptions.
- Execute dfFullscreenLayers[0].configure().
If you have more than one layer, you could use dfFullscreenLayers[k] as well (where k is the position of the layer you want to change in dfFullscreenLayers).
Example:
Imagine you want to change the side where the facets are positioned in the layer. The code you need to do this would be:
dfFullscreenLayers[0].layerOptions.display.facets.attached = "right";
dfFullScreenLayers[0].configure();
How to modify the search response
In certain situations you may want to customize the search response to modify some data. To do that you can register response processors that will receive the response object as an argument and must return it (modified or not) as the result so it can be passed to the layer components for rendering.
WARNING: Be careful, if you perform resource-intensive operations the layer rendering may slow down. Try to perform very simple operations and only when there’s no other way to get the desired results.
The best way to register a processor is to use the loaded callback:
var changeTitle = function(result){
result.title += ' (processed)';
return result;
};
// …
{
callbacks: {
loaded: function(instance) {
// Register a processor that changes the title of the results
instance.layer.controller.processors.push(function(response){
response.results = response.results.map(changeTitle);
return response;
});
}
}
}
You can add more than one processor. All processors will be executed in order, receiving the result returned by the previous processor executed.