unbxdSearch.js library can be used to integrated UNBXD search and category page on client side. It supports History API, so users can share the URI.
Note : This library makes use of jQuery selectors and Handlebars templates.
Please find an example of implementation in demo folder.
Just include unbxdSearch.js in HTML and include the configuration.
Consider a normal search page with basic layout as shown in the figure below and respective configuration below the image.
window.searchobj = new Unbxd.setSearch({
siteName : 'demo-u1393483043451'
,APIKey : 'ae30782589df23780a9d98502388555f'
,type : 'search'
,getCategoryId : ''
,inputSelector : '#search_input'
,searchButtonSelector : '#search_button'
,spellCheck : '#did_you_mean'
,spellCheckTemp : 'Did you mean : {{suggestion}} ?'
,searchQueryDisplay : '#search_title'
,searchQueryDisplayTemp : 'Showing results for {{query}} - {{start}}-{{end}} of {{numberOfProducts}} Results'
,pageSize : 12
,searchResultSetTemp : ['{{#products}}<li><a href="https://github.com/unbxd/js-sdk/blob/master/product.html?pid={{uniqueId}}" id="pdt-{{uniqueId}}" class="result-item" unbxdParam_sku="{{uniqueId}}" unbxdParam_pRank="{{unbxdprank}}" unbxdAttr="product">'
,'<div class="result-image-container">'
,'<span class="result-image-horizontal-holder">'
,'<img src="https://github.com/unbxd/js-sdk/raw/master/{{{image_url}}}" alt="{{{title}}}">'
,'</span>'
,'</div>'
,'<div class="result-brand">{{{brand}}}</div>'
,'<div class="result-title">{{{title}}}</div>'
,'<div class="result-price">'
,'${{price}}'
,'</div>'
,'</a></li>{{/products}}'].join('')
,searchResultContainer : '#results_container'
,isClickNScroll: false
,clickNScrollSelector : ''
,isAutoScroll : true
,facetTemp : ['{{#facets}}<div class="facet-block">'
,'<h3>{{name}}</h3>'
,'<div class="facet-values">'
,'<ul>'
,'{{#selected}}'
,'<li unbxdParam_facetName="{{../facet_name}}" unbxdParam_facetValue="{{value}}">'
,'<label for="{{../facet_name}}_{{value}}">'
,'<input type="checkbox" checked class="filter-checkbox" unbxdParam_facetName="{{../facet_name}}" unbxdParam_facetValue="{{value}}" id="{{../facet_name}}_{{value}}"> {{prepareFacetValue value}} ({{count}})'
,'</label>'
,'</li>'
,'{{/selected}}'
,'{{#unselected}}'
,'<li unbxdParam_facetName="{{../facet_name}}" unbxdParam_facetValue="{{value}}">'
,'<label for="{{../facet_name}}_{{value}}">'
,'<input type="checkbox" class="filter-checkbox" unbxdParam_facetName="{{../facet_name}}" unbxdParam_facetValue="{{value}}" id="{{../facet_name}}_{{value}}"> {{prepareFacetValue value}} ({{count}})'
,'</label>'
,'</li>'
,'{{/unselected}}'
,'</ul>'
,'</div>'
,'</div>{{/facets}}'
,'{{#rangefacets}}<div class="facet-block"'
,'<h3>{{name}}</h3>'
,'<div class="facet-values">'
,'<ul>'
,'{{#selected}}'
,'<li unbxdParam_facetName="{{../facet_name}}" unbxdParam_facetValue="{{value}}">'
,'<label for="{{../facet_name}}_{{value}}">'
,'<input type="checkbox" checked class="filter-checkbox" unbxdParam_facetName="{{../facet_name}}" unbxdParam_facetValue="{{value}}" id="{{../facet_name}}_{{value}}"> {{prepareFacetValue begin}} - {{prepareFacetValue end}} ({{count}})'
,'</label>'
,'</li>'
,'{{/selected}}'
,'{{#unselected}}'
,'<li unbxdParam_facetName="{{../facet_name}}" unbxdParam_facetValue="{{value}}">'
,'<label for="{{../facet_name}}_{{value}}">'
,'<input type="checkbox" class="filter-checkbox" unbxdParam_facetName="{{../facet_name}}" unbxdParam_facetValue="{{value}}" id="{{../facet_name}}_{{value}}"> {{prepareFacetValue begin}} - {{prepareFacetValue end}} ({{count}})'
,'</label>'
,'</li>'
,'{{/unselected}}'
,'</ul>'
,'</div>'
,'</div>{{/rangefacets}}'].join('')
,facetContainerSelector : "#facets_container"
,facetCheckBoxSelector : "input[type='checkbox']"
,facetElementSelector : "label"
,facetOnSelect : function(el){
//jQuery(el).addClass('selected');
}
,facetOnDeselect : function(el){
//jQuery(el).removeClass('selected');
}
,facetMultiSelect : true
,selectedFacetTemp : ['{{#each filters}}'
,'{{#each this}}'
,'<div class="selected-facet clearfix">'
,'<div class="selected-facet-name lt">{{{prepareFacetValue @key}}}</div>'
,'<div class="selected-facet-delete rt" unbxdParam_facetName="{{this}}" unbxdParam_facetValue="{{@key}}">×</div>'
,'</div>'
,'{{/each}}'
,'{{/each}}'
'{{#each ranges}}'
,'{{#each this}}'
,'<div class="selected-facet clearfix">'
,'<div class="selected-facet-name lt">{{{prepareFacetValue @key}}}</div>'
,'<div class="selected-facet-delete rt" unbxdParam_facetName="{{this}}" unbxdParam_facetValue="{{@key}}">×</div>'
,'</div>'
,'{{/each}}'
,'{{/each}}'].join('')
,selectedFacetContainerSelector : "#selected_facets"
,clearSelectedFacetsSelector : "#clear_all_selected_facets"
,removeSelectedFacetSelector : ".selected-facet-delete"
,selectedFacetHolderSelector : ""
,loaderSelector : ""//".result-loader"
,onFacetLoad : function(obj){}
,sanitizeQueryString : function(q){ return q;}
,getFacetStats : ""
,processFacetStats : function(obj){}
,setDefaultFilters : function(){}
,onIntialResultLoad : function(obj){}
,onPageLoad : function(obj){}
,onNoResult : function(obj){}
,facetMultilevel: true
,facetMultilevelName: 'CATEGORY'
,mappedFields: {
'price': price,
'title': name,
'imageUrl': imageurl,
'description': desc,
'variantFields': {
'v_imageUrl':v_imageUrl,
'v_productUrl':v_productUrl,
'v_price':v_price,
'v_title':v_title
}
}
,variants: false,
,bannerSelector: ".banner"
,bannerTemp: "<a href='{{landingUrl}}'><img src='{{imageUrl}}'/></a>"
,fields : ['image_url','title','brand','price','uniqueId']
,searchQueryParam:"q"
,retainbaseParam: false
,baseParams:[]
});
spellCheckTemp : Handlebars template for generating the spell suggestion template.
...
,spellCheck : '#did_you_mean'
,spellCheckTemp : 'Did you mean : {{suggestion}} ?'
...
//JSON used for this template
{
suggestion : "something else"
}
searchQueryDisplayTemp : Handlebars template for displaying the search query and total number of results. Please ignore incase of browse.
...
,searchQueryDisplay : '#search_title'
,searchQueryDisplayTemp : 'Search results for {{query}} - Showing {{start}}-{{end}} of {{numberOfProducts}} Results'
...
//JSON used for this template
{
query : "something"
,numberOfProducts : 1234
,start: 1
,end: 24
}
searchResultSetTemp : Handlebars template for the repetitive result block to display the individual product. This can also be function which take a single argument (a JSON block as shown below).
//handlebars helper, to get first element from array
Handlebars.registerHelper('getFirst', function(arr){
return arr.length > 0 ? arr[0] : "http://www.cdn.com/dummy.png";
});
//configuration
...
,searchResultSetTemp : ['{{#products}}<li><a href="https://github.com/unbxd/js-sdk/blob/master/product.html?pid={{uniqueId}}" id="pdt-{{uniqueId}}" class="result-item" unbxdParam_sku="{{uniqueId}}" unbxdParam_pRank="{{unbxdprank}}" unbxdAttr="product">'
,'<div class="result-image-container">'
,'<span class="result-image-horizontal-holder">'
,'<img src="https://github.com/unbxd/js-sdk/raw/master/{{{image_url}}}" alt="{{{title}}}">'
,'</span>'
,'</div>'
,'<div class="result-brand">{{{brand}}}</div>'
,'<div class="result-title">{{{title}}}</div>'
,'<div class="result-price">'
,'${{price}}'
,'</div>'
,'</a></li>{{/products}}'].join('')
,searchResultContainer : '#results_container'
...
//JSON used for this template
{
products : [
{
uniqueId : "SKU_1"
,imageUrl : "http://www.cdn.com/image1.png"
,title : "First product title"
,price : 2345
}
,{
uniqueId : "SKU_2"
,imageUrl : "http://www.cdn.com/image2.png"
,title : "Second product title"
,price : 1234
}
]
}
It can also contain multiple templates to include different view types(grid view/list view) like below:
,searchResultSetTemp:
{
"grid":
['{{#products}}<li class="grid_view"><a href="https://github.com/unbxd/js-sdk/blob/master/product.html?pid={{uniqueId}}" id="pdt-{{uniqueId}}" class="result-item" unbxdParam_sku="{{uniqueId}}" unbxdParam_pRank="{{unbxdprank}}" unbxdAttr="product">'
,'<div class="result-image-container">'
,'<span class="result-image-horizontal-holder">'
,'<img src="https://github.com/unbxd/js-sdk/raw/master/{{{image_url}}}" alt="{{{title}}}">'
,'</span>'
,'</div>'
,'<div class="result-brand">{{{brand}}}</div>'
,'<div class="result-title">{{{title}}}</div>'
,'<div class="result-price">'
,'${{price}}'
,'</div>'
,'</a></li>{{/products}}'].join(''),
"list":
['{{#products}}<li class="list_view"><a href="https://github.com/unbxd/js-sdk/blob/master/product.html?pid={{uniqueId}}" id="pdt-{{uniqueId}}" class="result-item" unbxdParam_sku="{{uniqueId}}" unbxdParam_pRank="{{unbxdprank}}" unbxdAttr="product">'
,'<div class="result-image-container">'
,'<span class="result-image-horizontal-holder">'
,'<img src="https://github.com/unbxd/js-sdk/raw/master/{{{image_url}}}" alt="{{{title}}}">'
,'</span>'
,'</div>'
,'<div class="result-brand">{{{brand}}}</div>'
,'<div class="result-title">{{{title}}}</div>'
,'<div class="result-price">'
,'${{price}}'
,'</div>'
,'</a></li>{{/products}}'].join('')
}
In this case, we need to also mention the different view types under 'viewTypes':
,viewTypes: ['grid', 'list']
,viewTypeContainerSelector: '.view_type_select'
,viewTypeContainerTemp:
'{{#options}}'
+'<li class="nxt-{{#if selected}}current{{/if}}">'
+'<a title="{{value}} View" class="nxt-{{value}}view-button" {{#unless selected}}unbxdviewtype="{{value}}"{{/unless}}>'
+'<span class="icon-{{value}}view">'
+'</span>'
+'</a>'
+'</li>'
+'{{/options}}'
JSON used for this template:
{
options: [{
"selected": true,
"value": "grid"
},
{
"selected": false,
"value": "list"
}]
}
searchResultContainer : The jQuery selector of DOM element to append the HTML generated from searchResultSetTemp (#results_container in the first image).
isClickNScroll : Set it to true if you want users to click an element to fetch the next page.
clickNScrollSelector : The jQuery selector of the DOM element that can be clicked for displaying the next page.(PS. in this case the new results will be appended to the searchResultContainer.)
isAutoScroll : Set this to true if you want the new pages to be displayed while user scrolls to the bottom of page.
facetTemp : Handlebars template for the repetitive facet block to display the individual facet. This can also be function which take a single argument (a JSON block as shown below).
//configuration
...
,facetTemp : ['{{#facets}}<div class="facet-block">'
,'<h3>{{name}}</h3>'
,'<div class="facet-values">'
,'<ul>'
,'{{#selected}}'
,'<li unbxdParam_facetName="{{../facet_name}}" unbxdParam_facetValue="{{value}}">'
,'<label for="{{../facet_name}}_{{value}}">'
,'<input type="checkbox" checked class="filter-checkbox" unbxdParam_facetName="{{../facet_name}}" unbxdParam_facetValue="{{value}}" id="{{../facet_name}}_{{value}}"> {{prepareFacetValue value}} ({{count}})'
,'</label>'
,'</li>'
,'{{/selected}}'
,'{{#unselected}}'
,'<li unbxdParam_facetName="{{../facet_name}}" unbxdParam_facetValue="{{value}}">'
,'<label for="{{../facet_name}}_{{value}}">'
,'<input type="checkbox" class="filter-checkbox" unbxdParam_facetName="{{../facet_name}}" unbxdParam_facetValue="{{value}}" id="{{../facet_name}}_{{value}}"> {{prepareFacetValue value}} ({{count}})'
,'</label>'
,'</li>'
,'{{/unselected}}'
,'</ul>'
,'</div>'
,'</div>{{/facets}}'
,'{{#rangefacets}}<div class="facet-block"'
,'<h3>{{name}}</h3>'
,'<div class="facet-values">'
,'<ul>'
,'{{#selected}}'
,'<li unbxdParam_facetName="{{../facet_name}}" unbxdParam_facetValue="{{value}}">'
,'<label for="{{../facet_name}}_{{value}}">'
,'<input type="checkbox" checked class="filter-checkbox" unbxdParam_facetName="{{../facet_name}}" unbxdParam_facetValue="{{value}}" id="{{../facet_name}}_{{value}}"> {{prepareFacetValue begin}} - {{prepareFacetValue end}} ({{count}})'
,'</label>'
,'</li>'
,'{{/selected}}'
,'{{#unselected}}'
,'<li unbxdParam_facetName="{{../facet_name}}" unbxdParam_facetValue="{{value}}">'
,'<label for="{{../facet_name}}_{{value}}">'
,'<input type="checkbox" class="filter-checkbox" unbxdParam_facetName="{{../facet_name}}" unbxdParam_facetValue="{{value}}" id="{{../facet_name}}_{{value}}"> {{prepareFacetValue begin}} - {{prepareFacetValue end}} ({{count}})'
,'</label>'
,'</li>'
,'{{/unselected}}'
,'</ul>'
,'</div>'
,'</div>{{/rangefacets}}'].join('')
...
//JSON used for generation is
{
"facets": [//this is an array
{
"name": "Category",//to display as title for facet
"facet_name": "Category_fq",//actual internal facet name
"type": "facet_fields",
"selected": [
{
"value": "Shirts",
"count": 114
},
{
"value": "Shoes",
"count": 29
}
],
"unselected": [
{
"value": "Footwear",
"count": 27
},
{
"value": "Jackets",
"count": 27
},
{
"value": "Accessories",
"count": 8
}
]
}
],
"rangefacets": [//this is an array
{
"name": "Price", //to display title for range facet
"facet_name": "Price_fq", //actual internal range facet name
"type": "facet_ranges",
"selected": [
{
"value": "200 TO 300",
"begin": "200",
"end": "300",
"count": 352
}
],
unselected: [
{
"value": "0 TO 100",
"begin": "0",
"end": "100",
"count": 44
},
{
"value": "100 TO 200",
"begin": "100",
"end": "200",
"count": 74
}
]
}
]
}
Note:
facetContainerSelector : The jQuery selector of DOM element to append the HTML generated from facetTemp (#facets_container in the first image).
facetCheckBoxSelector : jQuery selector for checkbox(input.filter-checkbox from facet template).
facetElementSelector : The parent element of checkbox which has to be returned the next config options (in the given facetTemp, it can be label or li).
facetOnSelect : This is function with single argument as DOM element of type given in facetElementSelector and executed when a facet is selected.
facetOnDeselect : This is function with single argument as DOM element of type given in facetElementSelector and executed when a facet is deselected.
facetMultiSelect : Set this value to false, incase if you dont want to enable multiselect on facets. It has a default value true.
selectedFacetTemp : Handlebars template for generating HTML to show the currently selected filters. Please check below image and code snippet.
//configuration
...
,selectedFacetTemp : ['{{#each filters}}'
,'{{#each this}}'
,'<div class="selected-facet clearfix">'
,'<div class="selected-facet-name lt">{{{prepareFacetValue @key}}}</div>'
,'<div class="selected-facet-delete rt" unbxdParam_facetName="{{this}}" unbxdParam_facetValue="{{@key}}">×</div>'
,'</div>'
,'{{/each}}'
,'{{/each}}'
,'{{#each ranges}}'
,'{{each this}}'
,'<div class="selected-facet clearfix">'
,'<div class="selected-facet-name lt">{{{prepareFacetValue @key}}}</div>'
,'<div class="selected-facet-delete rt" unbxdParam_facetName="{{this}}" unbxdParam_facetValue="{{@key}}">×</div>'
,'</div>'
,'{{/each}}'
'{{/each}}'].join('')
...
//JSON used for above template
{
"filters": {
"Category_fq": {
//the name of parent property is duplicated for rendering purpose
"Shirts": "Category_fq",
"Shoes": "Category_fq"
}
},
"ranges": {
"Price_fq": {
"200 TO 300": "Price_fq",
"300 TO 400": "Price_fq"
}
}
}
selectedFacetContainerSelector : jQuery selector of DOM element to place the generated HTML from selectedFacetTemp. (Please refer to above image.)
clearSelectedFacetsSelector : jQuery selector of DOM element on click which removes all the selected filters.(Please refer to above image.)
removeSelectedFacetSelector : jQuery selector of DOM element to remove respective filter.(This is useful in removing single filter. Example selected-facet-delete from above template. Please refer to above image.)
selectedFacetHolderSelector : jQuery selector of DOM element which
loaderSelector : The jQuery selector of the loading GIF image. This will be shown during the fetching process and hidden after the call.
onFacetLoad : This option takes a function which will be called after rendering the facet block, with the search response as its first argument.
sanitizeQueryString : This option should be a function with single argument as query which modifies and returns a new query against which the search has to be performed.
//configuration
...
,sanitizeQueryString : function (query){
//simple to condition which check if search query has min length of 3 or not
if(query && query.length > 2){
return query;
}else
return '';
}
...
getFacetStats : The field for which you want to get stats for. General example is price or discouts.
processFacetStats : This options is a function which takes single argument (a JSON) of the stats. This can be used to set a price slider.
//configuration
...
,processFacetStats : function(obj){
//set up the price slider here
jQuery("#price-slider").slider({
range: !0
,animate: !0
,min: obj.price.min
,max: obj.price.max
,values: [obj.price.values.min, obj.price.values.max]
,create: function() {
jQuery("#amount").html(obj.price.values.min +' - '+ obj.price.values.max);
},slide: function(b, c) {
jQuery("#amount").html(c.values[0] +' - '+ c.values[1]);
},change: function(b, c) {
searchobj
.clearRangeFiltes()
.addRangeFilter("price",c.values[0],c.values[1])
.setPage(1)
.callResults(searchobj.paintOnlyResultSet,true);
}
})
}
...
//sample JSON object for stats
{
price:
{
min : 90 //complete min value in result set
,max: 400 //complete max value in result set
//the above 2 values can be used to set the whole range of slider
,count : 30283
,sum: 7411762
,mean:244.7499257008883
,values:{
min:100 //selected min value if user has changed the range else complete min value in result set
,max:300//selected max value if user has changed the range else complete max value in result set
//the above 2 values are for setting the slider positions
}
}
}
setDefaultFilters : This option is a function which can be used to set default filters and/or sorts. An example implementation is below.
...
,setDefaultFilters : function(){
//to make the results by default sorted by quantity
this.addQueryParam('sort',"quantity desc");
//to make default filter by category shoes
this.addFilter('category_fq', 'shoes');
}
...
onIntialResultLoad : This option takes a function which will be executed after rendering of first result page with the search response as its first argument.
onPageLoad : This option takes a function which will be executed after rendering of new result page from second page with the search response as its first argument.
onNoResult : This option takes a function which will be executed if there are no results available.
bannerSelector : The jQuery selector for the container where the banner needs to be displayed.
bannerTemp : The template to be used when rendering the banner.
isPagination : Set to true when using pagination, also set isAutoScroll to false when this is set to true
paginationContainerSelector : The jQuery selector for the container where pagination needs to be displayed.
paginationTemp : The template to be used when rendering pagination
//configuration
,paginationTemp: ['{{#if hasFirst}}',
'<span class="unbxd_first" unbxdaction="first"> « </span>',
'{{/if}}',
'{{#if hasPrev}}',
'<span class="unbxd_prev" unbxdaction="prev"> < </span>',
'{{/if}}',
'{{#pages}}',
'{{#if current}}',
'<span class="unbxd_page highlight"> {{page}} </span>',
'{{else}}',
'<span class="unbxd_page" unbxdaction="{{page}}"> {{page}} </span>',
'{{/if}}',
'{{/pages}}',
'<span class="unbxd_pageof"> of </span>',
'<span class="unbxd_totalPages" unbxdaction="{{totalPages}}">{{totalPages}}</span>',
'{{#if hasNext}}',
'<span class="unbxd_next" unbxdaction="next"> > </span>',
'{{/if}}',
'{{#if hasLast}}',
'<span class="unbxd_last" unbxdaction="last">»</span>',
'{{/if}}'
].join('')
//JSON used for the above template
{
hasFirst: false,
hasPrev: false,
pages: [{
page: 1,
current: false
},{
page: 2,
current: false
},{
page: 3,
current: true
},{
page: 4,
current: false
},{
page: 5,
current: false
}]
totalPages: 42,
hasNext: true,
hasLast: true
}
sortContainerSelector : The jQuery selector for the container where sort template needs to be displayed
sortOptions : An array of objects containing the name, fieldname and order. These options will be used to display the sort options available
sortContainerType : Specifies the type of sort container. The value can be either 'select' or 'click'
sortContainerTemp : The template to be used when rendering the sort options
//configuration
...
,sortOptions: [{
name: 'Relevancy'
},{
name: 'Price: H-L',
field: 'price',
order: 'desc'
},{
name: 'Price: L-H',
field: 'price',
order: 'asc'
}]
,sortContainerType: 'select'
,sortContainerTemp: [
'<select>',
'{{#options}}',
'{{#if selected}}',
'<option value="{{field}}-{{order}}" unbxdsortField="{{field}}" unbxdsortValue="{{order}}" selected>{{name}}</option>',
'{{else}}',
'<option value="{{field}}-{{order}}" unbxdsortField="{{field}}" unbxdsortValue="{{order}}">{{name}}</option>',
'{{/if}}',
'{{/options}}',
'</select>'
].join('')
...
//sample JSON for sort
{
options: [{
name: 'Relevancy',
selected: true
},{
name: 'Price: H-L',
field: 'price',
order: 'desc',
selected: false
},{
name: 'Price: L-H',
field: 'price',
order: 'asc',
selected: false
}]
}
pageSizeContainerSelector : The jQuery selector for the container where page size template needs to be displayed
pageSizeOptions : An array of objects containing the name and value. These options will be used to display the page size options available
pageSizeContainerType : Specifies the type of page size container. The value can be either 'select' or 'click'
pageSizeContainerTemp : The template to be used when rendering the page size options
//configuration
...
,pageSizeOptions: [{
name: '12',
value: '12'
},{
name: '24',
value: '24'
},{
name: '36',
value: '36'
}]
,pageSizeContainerType: 'select'
,pageSizeContainerTemp: [
'<select>',
'{{#options}}',
'{{#if selected}}',
'<option value="{{value}}" selected unbxdpageSize="{{value}}">{{name}}</option>',
'{{else}}',
'<option value="{{value}}" unbxdpageSize="{{value}}">{{name}}</option>',
'{{/if}}',
'{{/options}}',
'</select>'
].join('')
...
//sample JSON for page size
{
options: [{
name: '12',
value: '12',
selected: true
},{
name: '24',
value: '24',
selected: false
},{
name: '36',
value: '36',
selected: false
}]
}
fields : This is an array of all required fields for generating result template. This is helpful to load the results faster. An example implementation is below
...
,fields : ['image_url','title','brand','price','uniqueId']
...
mappedFields : Mapping from Unbxd fields to catalog fields Ex: 'price': price. variantFields: Mapping of fields of variant products. Ex: variantFields: {v_imageUrl: v_imageurl} Similarly for price, title etc. variantFields.groupBy: Required for swatches to group variants data based on given 'groupBy' field.
facetMultilevel : Set this to true for category facets. Default is true
facetMultilevelName : Display name of category facets
variants : Set this to true, if client has variant products to display in the search view. Default is false
searchQueryParam : searh query param name to be shown in browser url, default is "q"
retainbaseParam : Set this to true, if you want to retain some extra url params from the SRP
baseParams : Array of params which will be retained from SRP. This will come into picture only if retainbaseParam is set to true
deferInitRender : This is an array of library features that need to be disabled on initial load.
...
,deferInitRender: ['search']
...
// The above config means the search results wont be rendered by the SDK on the first page.
// The other pages though, will be rendered by the SDK.
Note: The HTML served by the server to client should have the minimum requred structure. Check the below image.
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>UNBXD - Search</title>
<link rel="stylesheet" type="text/css" href="https://github.com/unbxd/js-sdk/blob/master/css/style.css">
<script type="text/javascript" src="https://github.com/unbxd/js-sdk/raw/master/jquery-1.9.1.js"></script>
<script type="text/javascript" src="https://github.com/unbxd/js-sdk/raw/master/handlebars.js"></script>
<script type="text/javascript" src="https://github.com/unbxd/js-sdk/raw/master/unbxdSearch.js"></script>
</head>
<body>
<div class="header-container clearfix">
<div class="header row clearfix">
<div class="header-search">
<div class="search-input-button-holder clearfix">
<form method="GET" action="search.html">
<input type="text" class="search-input lt" id="search_input" value="" unbxdattr="sq" name="q" autocomplete="off"/>
<button type="submit" class="search-button lt" id="search_button" unbxdattr="sq_bt"></button>
</form>
</div>
</div>
</div>
</div>
<div class="search-container">
<div class="row clearfix">
<div class="lt search-facet-column" id="facets_container">
</div>
<div class="rt search-result-column">
<h2 class="result-spell-check" id="did_you_mean">
</h2>
<h3 class="result-title-count" id="search_title">
</h3>
<div class="result-selected-facets clearfix" id="selected_facets">
</div>
<ul class="search-result-list clearfix" id="results_container">
</ul>
<div class="result-loader" id="ajax_loader">
<a href="#"><img src="https://github.com/unbxd/js-sdk/raw/master/images/loader.gif">Loading more...</a>
</div>
</div>
</div>
</div>
<div class="footer">
Copyright © 2014 Unbxd
</div>
<script type="text/javascript">
jQuery(function(){
//search configuration here
});
</script>
</body>
</html>