@searchstax-inc/searchstudio-ux-js
v4.1.47
Published
Library to build Site Search page
Keywords
Readme
sitesearch-ux-js
Library to build Site Search page
Installation
npm install following package
npm install --save @searchstax-inc/searchstudio-ux-js
Usage
After importing Searchstax class a new instance needs to be created:
const searchstax = new Searchstax();
Initialization
Initialization object needs to be of type: ISearchstaxConfig
interface ISearchstaxConfig {
sessionId?: string; // session id that is used for tracking. if not defined random value will be generated
language: string; // language code. Example: 'en'
model?: string; // Site Search model name.
searchURL: string; // Site Search select endpoint
suggesterURL: string; //Site Search suggest endpoint
trackApiKey: string; // Api key used for tracking events
searchAuth: string; // Authentication value. based on authType it's either a token value or basic auth value
authType: "token" | "basic"; // Type of authentication
autoCorrect?: boolean; // if set to true it will autoCorrect misspelled words. Default is false
router?: IRouterConfig; // optional object containing router settings
analyticsBaseUrl?: string; // url for analytics calls
questionURL?: string; // url for AI answer widget
hooks?: {
// optional object that provides various hook options
beforeSearch?: (props: ISearchObject) => ISearchObject | null; // this function gets called before firing search. searchProps are being passed as a property and can be modified, if passed along further search will execute with modified properties, if null is returned then event gets canceled and search never fires.
afterSearch?: (results: ISearchstaxParsedResult[]) => ISearchstaxParsedResult[]; // this function gets called after firing search and before rendering. It needs to return array of results that are either modified or untouched.
};
}Initialization example
searchstax.initialize({
language: "en",
model: "Main Profile",
searchURL: "",
suggesterURL: "",
trackApiKey: "",
searchAuth: "",
sessionId: "yourSessionId",
authType: "basic",
questionURL: "",
router: {
enabled: true,
routeName: "searchstax",
title: (result: ISearchObject) => {
return "Search results for: " + result.query;
},
ignoredKeys: [],
},
analyticsBaseUrl: 'https://analytics-us-east.searchstax.com',
hooks: {
beforeSearch: function (props: ISearchObject) {
const propsCopy = { ...props };
return propsCopy;
},
afterSearch: function (results: ISearchstaxParsedResult[]) {
const copy = [...results];
return copy;
},
}
});Initial layout
Our base theme is designed with this layout in mind but it is optional as all widgets have id parameters and can be attached to any element.
<div class="searchstax-page-layout-container">
<div id="searchstax-input-container"></div>
<div class="search-details-container">
<div id="search-feedback-container"></div>
<div id="search-sorting-container"></div>
</div>
<div class="searchstax-page-layout-facet-result-container">
<div class="searchstax-page-layout-facet-container">
<div id="searchstax-facets-container"></div>
</div>
<div class="searchstax-page-layout-result-container">
<div id="searchstax-external-promotions-layout-container"></div>
<div id="searchstax-results-container"></div>
<div id="searchstax-related-searches-container"></div>
<div id="searchstax-pagination-container"></div>
</div>
</div>
</div>widgets
Following widgets are available:
advanced data flow subscriptions
Following widgets are available:
Answer Widget
SearchStax Site Search solution offers Native JS widgets to assist in building your custom search page.
The SearchstaxAnswerWidget component for JS provides an AI answer widget for your searches.
Usage
searchstax.addAnswerWidget("searchstax-answer-container", {
showMoreAfterWordCount: 100,
feedbackwidget: feedbackConfig
});Props
- showMoreAfterWordCount - number(default 100) determining after how many words UI will show “Read More” view.
- feedbackWidget – an optional object that configures thumbs-up and thumbs-down feedback functionality.
- templates - template override. look at examples below
Example of feedbackWidget config:
const feedbackConfig = {
renderFeedbackWidget: true,
emailOverride: searchstaxEmailOverride,
thumbsUpValue: 10,
thumbsDownValue: 0,
lightweightTemplateOverride: `
<div class="searchstax-lightweight-widget-container">
<div class="searchstax-lightweight-widget-thumbs-up {{#thumbsUpActive}}active{{/thumbsUpActive}}">
<svg width="17" height="17" viewBox="0 0 17 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4.85079 7.59996L7.83141 1C8.4243 1 8.9929 1.23178 9.41213 1.64436C9.83136 2.05694 10.0669 2.61651 10.0669 3.19999V6.1333H14.2845C14.5005 6.13089 14.7145 6.17474 14.9116 6.26179C15.1087 6.34885 15.2842 6.47704 15.426 6.63747C15.5677 6.79791 15.6723 6.98676 15.7326 7.19094C15.7928 7.39513 15.8072 7.60975 15.7748 7.81996L14.7465 14.4199C14.6926 14.7696 14.5121 15.0884 14.2382 15.3175C13.9643 15.5466 13.6156 15.6706 13.2562 15.6666H4.85079M4.85079 7.59996V15.6666M4.85079 7.59996H2.61531C2.22006 7.59996 1.84099 7.75448 1.5615 8.02953C1.28201 8.30458 1.125 8.67763 1.125 9.06661V14.1999C1.125 14.5889 1.28201 14.9619 1.5615 15.237C1.84099 15.512 2.22006 15.6666 2.61531 15.6666H4.85079" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</div>
<div class="searchstax-lightweight-widget-separator"></div>
<div class="searchstax-lightweight-widget-thumbs-down {{#thumbsDownActive}}active{{/thumbsDownActive}}">
<svg width="17" height="17" viewBox="0 0 17 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12.1492 9.06801L9.16859 15.668C8.5757 15.668 8.0071 15.4362 7.58787 15.0236C7.16864 14.611 6.93311 14.0515 6.93311 13.468V10.5347H2.71552C2.4995 10.5371 2.28552 10.4932 2.08842 10.4062C1.89132 10.3191 1.71581 10.1909 1.57405 10.0305C1.43229 9.87006 1.32766 9.6812 1.26743 9.47702C1.2072 9.27284 1.19279 9.05822 1.22521 8.84801L2.25353 2.24806C2.30742 1.89833 2.48793 1.57955 2.76179 1.35046C3.03566 1.12136 3.38443 0.997398 3.74384 1.0014H12.1492M12.1492 9.06801V1.0014M12.1492 9.06801H14.3847C14.7799 9.06801 15.159 8.91349 15.4385 8.63844C15.718 8.36339 15.875 7.99034 15.875 7.60135V2.46805C15.875 2.07907 15.718 1.70602 15.4385 1.43097C15.159 1.15592 14.7799 1.0014 14.3847 1.0014H12.1492" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</div>
</div>
`,
}searchAnswerTemplate
The templates prop allows customizing the answer UI.
It receives the following props:
- shouldShowAnswer – boolean
- answerErrorMessage – string
- fullAnswerFormatted – string
- showMoreButtonVisible – boolean
- answerLoading – boolean
Example
This example is based on sitesearch-ux-js:
searchstax.addAnswerWidget("searchstax-answer-container", {
showMoreAfterWordCount: 100,
templates: {
main: {
template: `
{{#shouldShowAnswer}}
<div class="searchstax-answer-wrap">
<div class="searchstax-answer-icon"></div>
<div>
<div class="searchstax-answer-container {{#showMoreButtonVisible}}searchstax-answer-show-more{{/showMoreButtonVisible}}">
<div class="searchstax-answer-title">Smart Answers</div>
{{#shouldShowAnswerError}}
<div class="searchstax-answer-error">{{{answerErrorMessage}}}</div>
{{/shouldShowAnswerError}}
<div class="searchstax-answer-description">
{{{fullAnswerFormatted}}}
{{^showMoreButtonVisible}}
{{#answerLoading}}
<div class="searchstax-answer-loading"></div>
{{/answerLoading}}
{{/showMoreButtonVisible}}
</div>
</div>
{{#showMoreButtonVisible}}
<div class="searchstax-answer-load-more-button-container">
{{#answerLoading}}
<div class="searchstax-answer-loading"></div>
{{/answerLoading}}
<button class="searchstax-answer-load-more-button">Read More</button>
</div>
{{/showMoreButtonVisible}}
</div>
<div class="searchstax-answer-footer">
<div id="feedbackWidgetContainer"></div>
<div class="searchstax-lightweight-widget-separator-inline"></div>
<p class="searchstax-disclaimer">Generative AI is Experimental</p>
</div>
</div>
{{/shouldShowAnswer}}
`,
answerContainerId: ``,
},
},
feedbackwidget: feedbackConfig
});Input Widget
The SearchStax Site Search solution’s Input widget provides the search input field with autosuggest/autocomplete capabilities.
Usage
searchstax.addSearchInputWidget("searchstax-input-container", {
suggestAfterMinChars: 3,
});Props
- suggestAfterMinChars - default 3. Number of characters needed for autosuggest to start triggering
- hooks.beforeAutosuggest - callback function that gets called before firing autosuggest. autosuggestProps are being passed as a property and can be modified, if passed along further search will execute with modified properties, if null is returned then event gets canceled and search never fires.
- hooks.afterAutosuggest - callback function that gets called after autosuggest has values but before rendering. It needs to return same type of data but it can be modified.
- templates - template override. look at examples below
inputWidgetTemplate
The templates prop allows customizing the input UI.
It receives the following props:
- locationEnabled – boolean
inputWidgetAutosuggestTemplate
The templates prop allows customizing the input autosuggest UI.
It receives the following props:
- term – suggested term
example
searchstax.addSearchInputWidget("searchstax-input-container", {
suggestAfterMinChars: 3,
hooks: {
afterAutosuggest: function (result: ISearchstaxSuggestResponse) {
const copy = { ...result };
return copy;
},
beforeAutosuggest: function (props: ISearchstaxSuggestProps) {
// gets suggestProps, if passed along further autosuggest will execute, if null then event gets canceled
// props can be modified and passed along
const propsCopy = { ...props };
// propsCopy.term = propsCopy.term + '222';
return propsCopy;
},
},
templates: {
mainTemplate: {
template: `
<div class="searchstax-search-input-container searchstax-search-input-container-new {{#locationEnabled}}searchstax-alternative-render{{/locationEnabled}}">
<div class="searchstax-search-input-wrapper">
<input type="text" id="searchstax-search-input" class="searchstax-search-input" placeholder="SEARCH FOR..." aria-label="Search" />
</div>
<div id="searchstax-location-container" class="searchstax-location-container"></div>
<button class="searchstax-spinner-icon" id="searchstax-search-input-action-button" aria-label="search" role="button"></button>
</div>
`,
searchInputId: "searchstax-search-input"
}
autosuggestItemTemplate: {
template: `
<div class="searchstax-autosuggest-item-term-container">{{{term}}}</div>
`,
}
},
});Location Widget
SearchStax Site Search solution offers a native JS search-location widget to assist with your custom search page.
The SearchstaxLocationWidget provides a location search input with location-based search functionality.
Usage
function locationDecodeFunction(term: string): Promise<ISearchstaxLocation>{
return new Promise((resolve) => {
// make a request to geocoding API to retrieve lat, lon and address and then resolve promise
resolve({
address:'Address',
lat: lat,
lon: lon,
error: false
});
});
}
function locationDecodeCoordinatesToAddress(lat, lon): Promise<ISearchstaxLocation>{
return new Promise((resolve) => {
// make a request to geocoding API to convert lat, lon to address and then resolve promise
resolve({
address:'Address',
lat: lat,
lon: lon,
error: false
});
});
}
searchstax.addSearchLocationWidget("searchstax-location-container", {
hooks: {
locationDecode: locationDecodeFunction,
locationDecodeCoordinatesToAddress: locationDecodeCoordinatesToAddress
},
});Props
- hooks.locationDecode - callback function to override location decoding
- hooks.locationDecodeCoordinatesToAddress - callback function to override location decoding
- templates - see examples below
Template Override
The templates prop allows customizing the location input UI.
It receives the following props:
- locationSearchDistanceValues – location distance values
- shouldShowLocationDistanceDropdown – boolean determining if distance dropdown should be shown
Example
searchstax.addSearchLocationWidget("searchstax-location-container", {
templates:{
mainTemplate: {
template: `
<div class="searchstax-location-input-container" data-test-id="searchstax-location-input-container">
<div class="searchstax-location-input-wrapper">
<span class="searchstax-location-input-label">NEAR</span>
<div class="searchstax-location-input-wrapper-inner">
<input type="text" id="searchstax-location-input" class="searchstax-location-input" placeholder="Zip, Postal Code or City..." aria-label="Search Location Input" data-test-id="searchstax-location-input" />
<button id="searchstax-location-get-current-location" class="searchstax-get-current-location-button">Use my current location</button>
</div>
{{#shouldShowLocationDistanceDropdown}}
<span class="searchstax-location-input-label">WITHIN</span>
<select id="searchstax-location-radius-select" class="searchstax-location-radius-select" aria-label="Search Location Radius Select" data-test-id="searchstax-location-radius-select">
{{#locationSearchDistanceValues}}
<option value="{{value}}" {{#isSelected}}selected{{/isSelected}}>{{label}}</option>
{{/locationSearchDistanceValues}}
</select>
{{/shouldShowLocationDistanceDropdown}}
</div>
</div>
`,
locationInputId: "searchstax-location-input",
radiusInputId: "searchstax-location-radius-select"
},
},
hooks: {
locationDecode: locationDecodeFunction,
locationDecodeCoordinatesToAddress: locationDecodeCoordinatesToAddress
},
});Result Widget
The SearchStax Site Search solution’s Results Widget for UX-JS displays the search results.
Usage
searchstax.addSearchResultsWidget("searchstax-results-container", {});Props
- renderMethod – either “pagination” or “infiniteScroll”.
- resultsPerPage – number of results on a page.
- hooks.afterLinkClick – Callback function invoked when a result link is clicked. Allows modifying the result object.
- templates - see examples below
Main Template Override
The template prop allows customizing the result UI.
It receives no props:
Search Result Template Override
The template prop allows customizing the result UI.
It receives following props:
- custom?: any - custom properties that may be added through aftersearchHook
- ribbon: string | null
- paths: string | null;
- url: string | null;
- title: string | null;
- titleTracking: string | null;
- promoted: boolean | null;
- thumbnail: string | null;
- date: string | null;
- snippet: string | null;
- description: string | null;
- uniqueId: string;
- position: number;
- distance: number | null;
- unit: string | null;
- unmappedFields: { key: string; value: string | string[] | boolean; isImage?: boolean; }[] - fields that were not mapped.
- allFields: { key: string; value: string | string[] | boolean }[] - all fields
No Results Template Override
The template prop allows customizing the result UI.
It receives following props:
- spellingSuggestion - suggestion of corrected spelling
- searchExecuted - boolean if search was executed
- searchTerm - term that was searched
Example of default render method
searchstax.addSearchResultsWidget("searchstax-results-container", {
templates: {
mainTemplate: {
template: `
<section aria-label="search results container" tabindex="0">
<div class="searchstax-search-results-container" id="searchstax-search-results-container" data-test-id="searchstax-search-results-container">
<div class="searchstax-search-results" id="searchstax-search-results"></div>
</div>
</section>
`,
searchResultsContainerId: "searchstax-search-results",
},
searchResultTemplate: {
template: `
<a href="{{url}}" data-searchstax-unique-result-id="{{uniqueId}}" data-test-id="searchstax-result-item-link" class="searchstax-result-item-link searchstax-result-item-link-wrapping" tabindex="0" aria-labelledby="title-{{uniqueId}}">
<div class="searchstax-search-result searchstax-search-result-wrapping {{#thumbnail}} has-thumbnail {{/thumbnail}}">
{{#promoted}}
<div class="searchstax-search-result-promoted" data-test-id="searchstax-search-result-promoted"></div>
{{/promoted}}
{{#ribbon}}
<div class="searchstax-search-result-ribbon" data-test-id="searchstax-search-result-ribbon">
{{{ribbon}}}
</div>
{{/ribbon}}
{{#thumbnail}}
<img alt="" src="{{thumbnail}}" alt="image" class="searchstax-thumbnail" data-test-id="searchstax-thumbnail">
{{/thumbnail}}
<div class="searchstax-search-result-title-container" data-test-id="searchstax-search-result-title-container">
<h3 class="searchstax-search-result-title" id="title-{{uniqueId}}">{{{title}}}</h3>
</div>
{{#paths}}
<p class="searchstax-search-result-common" tabindex="0" data-test-id="searchstax-search-result-common">
{{{paths}}}
</p>
{{/paths}}
{{#description}}
<p tabindex="0" class="searchstax-search-result-description searchstax-search-result-common" data-test-id="searchstax-search-result-description">
{{{description}}}
</p>
{{/description}}
{{#unmappedFields}}
{{#isImage}}
<div class="searchstax-search-result-image-container">
<img alt="" src="{{value}}" alt="image" class="searchstax-result-image" data-test-id="searchstax-result-image">
</div>
{{/isImage}}
{{^isImage}}
<p tabindex="0" class="searchstax-search-result-common">
{{{value}}}
</p>
{{/isImage}}
{{/unmappedFields}}
{{#distance}}
<p tabindex="0" class="searchstax-search-result-distance searchstax-search-result-common" data-test-id="searchstax-search-result-distance">
{{distance}} {{unit}}
</p>
{{/distance}}
</div>
</a>
`,
searchResultUniqueIdAttribute: "data-searchstax-unique-result-id"
},
noSearchResultTemplate: {
template: `
{{#searchExecuted}}
<div class="searchstax-no-results-wrap" data-test-id="searchstax-no-results-wrap">
<div class="searchstax-no-results" data-test-id="searchstax-no-results">
Showing <strong>no results</strong> for <strong>"{{ searchTerm }}"</strong>
<br>
{{#spellingSuggestion}}
<span> Did you mean <a href="#" aria-label="Did you mean: {{originalQuery}}" class="searchstax-suggestion-term" onclick="searchCallback('{{ spellingSuggestion }}')">{{ spellingSuggestion }}</a>?</span>
{{/spellingSuggestion}}
</div>
<ul class="searchstax-no-results-list" data-test-id="searchstax-no-results-list">
<li>Try searching for search related terms or topics. We offer a wide variety of content to help you get the information you need.</li>
<li>Lost? Click on the ‘X” in the Search Box to reset your search.</li>
</ul>
</div>
{{/searchExecuted}}
`
}
},
hooks: {
afterLinkClick: function (result: ISearchstaxParsedResult) {
// gets result that was clicked, if passed along further functions will execute, if null then event gets canceled
const propsCopy = { ...result };
return propsCopy;
},
},
});Example of infinite scroll render method
searchstax.addSearchResultsWidget("searchstax-results-container", {
templates: {
mainTemplate: {
template: `
<section aria-label="search results container" tabindex="0">
<div class="searchstax-search-results-container" id="searchstax-search-results-container" data-test-id="searchstax-search-results-container">
<div class="searchstax-search-results" id="searchstax-search-results"></div>
</div>
</section>
`,
searchResultsContainerId: "searchstax-search-results",
},
searchResultTemplate: {
template: `
<a href="{{url}}" data-searchstax-unique-result-id="{{uniqueId}}" data-test-id="searchstax-result-item-link" class="searchstax-result-item-link searchstax-result-item-link-wrapping" tabindex="0" aria-labelledby="title-{{uniqueId}}">
<div class="searchstax-search-result searchstax-search-result-wrapping {{#thumbnail}} has-thumbnail {{/thumbnail}}">
{{#promoted}}
<div class="searchstax-search-result-promoted" data-test-id="searchstax-search-result-promoted"></div>
{{/promoted}}
{{#ribbon}}
<div class="searchstax-search-result-ribbon" data-test-id="searchstax-search-result-ribbon">
{{{ribbon}}}
</div>
{{/ribbon}}
{{#thumbnail}}
<img alt="" src="{{thumbnail}}" alt="image" class="searchstax-thumbnail" data-test-id="searchstax-thumbnail">
{{/thumbnail}}
<div class="searchstax-search-result-title-container" data-test-id="searchstax-search-result-title-container">
<h3 class="searchstax-search-result-title" id="title-{{uniqueId}}">{{{title}}}</h3>
</div>
{{#paths}}
<p class="searchstax-search-result-common" tabindex="0" data-test-id="searchstax-search-result-common">
{{{paths}}}
</p>
{{/paths}}
{{#description}}
<p tabindex="0" class="searchstax-search-result-description searchstax-search-result-common" data-test-id="searchstax-search-result-description">
{{{description}}}
</p>
{{/description}}
{{#unmappedFields}}
{{#isImage}}
<div class="searchstax-search-result-image-container">
<img alt="" src="{{value}}" alt="image" class="searchstax-result-image" data-test-id="searchstax-result-image">
</div>
{{/isImage}}
{{^isImage}}
<p tabindex="0" class="searchstax-search-result-common">
{{{value}}}
</p>
{{/isImage}}
{{/unmappedFields}}
{{#distance}}
<p tabindex="0" class="searchstax-search-result-distance searchstax-search-result-common" data-test-id="searchstax-search-result-distance">
{{distance}} {{unit}}
</p>
{{/distance}}
</div>
</a>
`,
searchResultUniqueIdAttribute: "data-searchstax-unique-result-id"
},
noSearchResultTemplate: {
template: `
{{#searchExecuted}}
<div class="searchstax-no-results-wrap" data-test-id="searchstax-no-results-wrap">
<div class="searchstax-no-results" data-test-id="searchstax-no-results">
Showing <strong>no results</strong> for <strong>"{{ searchTerm }}"</strong>
<br>
{{#spellingSuggestion}}
<span> Did you mean <a href="#" aria-label="Did you mean: {{originalQuery}}" class="searchstax-suggestion-term" onclick="searchCallback('{{ spellingSuggestion }}')">{{ spellingSuggestion }}</a>?</span>
{{/spellingSuggestion}}
</div>
<ul class="searchstax-no-results-list" data-test-id="searchstax-no-results-list">
<li>Try searching for search related terms or topics. We offer a wide variety of content to help you get the information you need.</li>
<li>Lost? Click on the ‘X” in the Search Box to reset your search.</li>
</ul>
</div>
{{/searchExecuted}}
`
}
},
renderMethod: 'infiniteScroll',
resultsPerPage: 10,
hooks: {
afterLinkClick: function (result: ISearchstaxParsedResult) {
// gets result that was clicked, if passed along further functions will execute, if null then event gets canceled
const propsCopy = { ...result };
return propsCopy;
},
},
});Pagination Widget
The SearchStax Site Search solution’s Pagination Widget displays a pagination control for UX-JS.
Usage
searchstax.addPaginationWidget("searchstax-pagination-container", {});Props
- templates - see examples below
Multiple Instances
Multiple instances of the Pagination widget can be added by calling the addPaginationWidget method multiple times with different target containers:
searchstax.addPaginationWidget('container1', options1);
searchstax.addPaginationWidget('container2', options2);
Each instance can be configured separately via its options object. This allows for the widget to be added to different locations on the page as needed.
Main Template Override
Main template for the pagination controls.
It receives following props:
- nextPageLink - link of next page;
- previousPageLink - link of previous page;
Infinite Scroll Template Override
Main template for the pagination controls in infinite scroll mode.
It receives following props:
- isLastPage - boolean, true if its last page
- results - results.length can be used if there are results
Example
searchstax.addPaginationWidget("searchstax-pagination-container", {
templates: {
mainTemplate: {
template: `
{{#results.length}}
<div class="searchstax-pagination-container" data-test-id="searchstax-pagination-container">
<div class="searchstax-pagination-content">
<a role="link" class="searchstax-pagination-previous {{#isFirstPage}}disabled{{/isFirstPage}}" aria-disabled="{{#isFirstPage}}true{{/isFirstPage}}{{^isFirstPage}}false{{/isFirstPage}}" id="searchstax-pagination-previous" data-test-id="searchstax-pagination-previous" tabindex="0" aria-label="Previous Page">< Previous</a>
<div class="searchstax-pagination-details" data-test-id="searchstax-pagination-details">
{{startResultIndex}} - {{endResultIndex}} of {{totalResults}}
</div>
<a role="link" class="searchstax-pagination-next {{#isLastPage}}disabled{{/isLastPage}}" aria-disabled="{{#isLastPage}}true{{/isLastPage}}{{^isLastPage}}false{{/isLastPage}}" data-test-id="searchstax-pagination-next" id="searchstax-pagination-next" tabindex="0" aria-label="Next Page">Next ></a>
</div>
</div>
{{/results.length}}
`,
previousButtonClass: "searchstax-pagination-previous",
nextButtonClass: "searchstax-pagination-next"
},
infiniteScrollTemplate: {
template: `
{{#results.length}}
<div class="searchstax-pagination-container" data-test-id="searchstax-pagination-container">
<div class="searchstax-pagination-content">
<a role="link" class="searchstax-pagination-previous {{#isFirstPage}}disabled{{/isFirstPage}}" aria-disabled="{{#isFirstPage}}true{{/isFirstPage}}{{^isFirstPage}}false{{/isFirstPage}}" id="searchstax-pagination-previous" data-test-id="searchstax-pagination-previous" tabindex="0" aria-label="Previous Page">< Previous</a>
<div class="searchstax-pagination-details" data-test-id="searchstax-pagination-details">
{{startResultIndex}} - {{endResultIndex}} of {{totalResults}}
</div>
<a role="link" class="searchstax-pagination-next {{#isLastPage}}disabled{{/isLastPage}}" aria-disabled="{{#isLastPage}}true{{/isLastPage}}{{^isLastPage}}false{{/isLastPage}}" data-test-id="searchstax-pagination-next" id="searchstax-pagination-next" tabindex="0" aria-label="Next Page">Next ></a>
</div>
</div>
{{/results.length}}
`,
loadMoreButtonClass: "searchstax-pagination-load-more"
}
},
});Facets Widget
The SearchStax Site Search solution’s Facets Widget for UX-JS displays faceted filters for search.
Facet Selection and Order
Facet lists are configured and ordered on the Site Search Faceting Tab.
Usage
searchstax.addFacetsWidget("searchstax-facets-container", {
facetingType: "and",
itemsPerPageDesktop: 3,
itemsPerPageMobile: 99,
});Multiple Instances
Multiple instances of the Facets widget can be added by calling the addFacetsWidget method multiple times with different target containers:
searchstax.addFacetsWidget('container1', options1);
searchstax.addFacetsWidget('container2', options2);
Each instance can be configured separately via its options object. This allows for the widget to be added to different locations on the page as needed.
Props
- facetingType: "and" | "or" | "showUnavailable" | "tabs"; // type that determines how facets will behave
- specificFacets?: string[]; // optional array of facet names that if provided will only render those facets
- itemsPerPageDesktop: number; // default expanded facets for desktop
- itemsPerPageMobile: number; // default expanded facets for mobile
- templates - see examples below
Main Template Desktop Override
Main wrapper template for desktop facets display.
It receives following props from IFacetsTemplateData
Main Template Mobile Override
Main wrapper template for mobile facets display.
It receives following props from IFacetsTemplateData
Show More Button Container Override
Template for show more button
It receives following props:
- showingAllFacets - boolean true if showing all facets
Facet Item Container Template Override
Template for facet item container.
It receives following props:
- label - label of facet
Clear Facets Template Override
Template for clear facets.
It receives following props:
- shouldShow - boolean, true if it should be displayed
Facet Item Template Override
Template for facet item.
It receives following props:
- disabled - boolean, true if disabled
- isChecked - boolean, true if checked
- value - string, value of facet
- count - number of items for that facet
Filter By Template Override
Template for filter by.
It receives no props
Selected Facets Template Override
Template for selected facets.
It receives following props:
- value - string, value of facet
- count - number of items for that facet
Example
searchstax.addFacetsWidget("searchstax-facets-container", {
facetingType: "and",
itemsPerPageDesktop: 3,
itemsPerPageMobile: 99,
templates: {
mainTemplateDesktop: {
template: `
{{#hasResultsOrExternalPromotions}}
<div class="searchstax-facets-container-desktop"></div>
{{/hasResultsOrExternalPromotions}}
`,
facetsContainerId: "",
},
mainTemplateMobile: {
template: `
<div class="searchstax-facets-pills-container">
<div class="searchstax-facets-pills-selected">
</div>
</div>
<div class="searchstax-facets-mobile-overlay {{#overlayOpened}} searchstax-show{{/overlayOpened}}" data-test-id="searchstax-facets-mobile-overlay">
<div class="searchstax-facets-mobile-overlay-header">
<div class="searchstax-facets-mobile-overlay-header-title">Filter By</div>
<div class="searchstax-search-close" tabindex="0" aria-label="close overlay" role="button" data-test-id="searchstax-search-close"></div>
</div>
<div class="searchstax-facets-container-mobile"></div>
<button class="searchstax-facets-mobile-overlay-done" data-test-id="searchstax-facets-mobile-overlay-done">Done</button>
</div>
`,
facetsContainerClass: `searchstax-facets-container-mobile`,
closeOverlayTriggerClasses: ["searchstax-facets-mobile-overlay-done","searchstax-search-close",],
filterByContainerClass: `searchstax-facets-pills-container`,
selectedFacetsContainerClass: `searchstax-facets-pills-selected`,
},
showMoreButtonContainerTemplate: {
template: `
<div class="searchstax-facet-show-more-container" data-test-id="searchstax-facet-show-more-container">
{{#showingAllFacets}}
<div class="searchstax-facet-show-less-button searchstax-facet-show-button" tabindex="0" data-test-id="searchstax-facet-show-less-button" data-focus="{{focusId}}" role="button">less</div>
{{/showingAllFacets}}
{{^showingAllFacets}}
<div class="searchstax-facet-show-more-button searchstax-facet-show-button" tabindex="0" data-test-id="searchstax-facet-show-more-button" data-focus="{{focusId}}" role="button">more {{onShowMoreLessClick}}</div>
{{/showingAllFacets}}
</div>
`,
showMoreButtonClass: `searchstax-facet-show-more-container`,
},
facetItemContainerTemplate: {
template: `
<div>
<div class="searchstax-facet-title-container" data-test-id="searchstax-facet-title-container">
<div class="searchstax-facet-title" aria-label="Facet group: {{label}}" tabindex="0" role="button">
{{label}}
</div>
<div class="searchstax-facet-title-arrow active"></div>
</div>
<div class="searchstax-facet-values-container"></div>
</div>
`,
facetListTitleContainerClass: `searchstax-facet-title-container`,
facetListContainerClass: `searchstax-facet-values-container`,
},
clearFacetsTemplate: {
template: `
{{#shouldShow}}
<div class="searchstax-facets-pill searchstax-clear-filters searchstax-facets-pill-clear-all" tabindex="0" role="button" data-test-id="searchstax-facets-pill-clear-all">
<div class="searchstax-facets-pill-label">Clear Filters</div>
</div>
{{/shouldShow}}
`,
containerClass: `searchstax-facets-pill-clear-all`,
},
facetItemTemplate: {
template: `
<div class="searchstax-facet-input">
<input type="checkbox" class="searchstax-facet-input-checkbox" data-test-id="searchstax-facet-input-checkbox" {{#disabled}}disabled{{/disabled}} {{#isChecked}}checked{{/isChecked}} aria-label="{{value}} {{count}}" tabindex="0"/>
</div>
<div class="searchstax-facet-value-label" data-test-id="searchstax-facet-value-label">{{value}}</div>
<div class="searchstax-facet-value-count" data-test-id="searchstax-facet-value-count">({{count}})</div>
`,
inputCheckboxClass: `searchstax-facet-input-checkbox`,
checkTriggerClasses: ["searchstax-facet-value-label","searchstax-facet-value-count",],
},
filterByTemplate: {
template: `
<div class="searchstax-facets-pill searchstax-facets-pill-filter-by" tabindex="0" role="button" data-test-id="searchstax-facets-pill-filter-by" >
<div class="searchstax-facets-pill-label">Filter By</div>
</div>
`,
containerClass: `searchstax-facets-pill-filter-by`,
},
selectedFacetsTemplate: {
template: `
<div class="searchstax-facets-pill searchstax-facets-pill-facets" tabindex="0" role="button" data-test-id="searchstax-facets-pill-facets">
<div class="searchstax-facets-pill-label">{{value}} ({{count}})</div>
<div class="searchstax-facets-pill-icon-close"></div>
</div>
`,
containerClass: `searchstax-facets-pill-facets`,
},
},
});SearchFeedback Widget
The SearchStax Site Search solution’s Feedback Widget displays search feedback and stats for UX-JS.
Usage
searchstax.addSearchFeedbackWidget("search-feedback-container", {});Multiple Instances
Multiple instances of the SearchFeedback widget can be added by calling the addSearchFeedbackWidget method multiple times with different target containers:
searchstax.addSearchFeedbackWidget('container1', options1);
searchstax.addSearchFeedbackWidget('container2', options2);
Each instance can be configured separately via its options object. This allows for the widget to be added to different locations on the page as needed.
Props
- templates - see examples below
Main Template Override
Main template for the search feedback message.
It receives following props:
- searchExecuted - boolean, true if search was executed
- hasResults - boolean, true if search has results
- startResultIndex - number, start of page results
- endResultIndex - number, end of page results
- totalResults - number, total results
- searchTerm - term that was searched
- autoCorrectedQuery - query that search was autocorrected to
- originalQuery - original query
Example
searchstax.addSearchFeedbackWidget("search-feedback-container", {
templates: {
main: {
template: `
{{#searchExecuted}}
<a href="#searchstax-search-results" data-test-id="searchstax-skip" class="searchstax-skip">Skip to results section</a>
<h4 class="searchstax-feedback-container" data-test-id="searchstax-feedback-container">
{{#hasResults}}
<span> Showing <b>{{startResultIndex}} - {{endResultIndex}}</b> </span> of <b>{{totalResults}}</b> results {{#searchTerm}} for "<b>{{searchTerm}}</b>" {{/searchTerm}}
<div class="searchstax-feedback-container-suggested" data-test-id="searchstax-feedback-container-suggested">
{{#autoCorrectedQuery}}
Search instead for <a href="#" aria-label="Search instead for: {{originalQuery}}" class="searchstax-feedback-original-query" data-test-id="searchstax-feedback-original-query">{{originalQuery}}</a>
{{/autoCorrectedQuery}}
</div>
{{/hasResults}}
</h4>
{{/searchExecuted}}
`,
originalQueryClass: `searchstax-feedback-original-query`
}
},
});RelatedSearches widget
The SearchStax Site Search solution’s Related Searches Widget displays related searches for UX-JS.
Usage
searchstax.addRelatedSearchesWidget("searchstax-related-searches-container", {
relatedSearchesURL: "URL",
relatedSearchesAPIKey: "KEY"
})Props
- relatedSearchesURL: // : An endpoint from the Discovery tab of the App Settings > All APls screen.
- relatedSearchesAPIKey: The Discovery API key from the Discovery tab of the App Settings > All
- templates - see examples below
Main Template Override
Main template for related searches.
It receives following props:
- hasRelatedSearches - boolean, true if has related searches
- relatedSearches - array of related searches
Related Search Template Override
Related Search template.
It receives following props:
- related_search - string, related searc
- last - boolean, true if last related search
Example
searchstax.addRelatedSearchesWidget("searchstax-related-searches-container", {
relatedSearchesURL: "URL",
relatedSearchesAPIKey: "KEY",
templates: {
main: {
template: `
{{#hasRelatedSearches}}
<div class="searchstax-related-searches-container" data-test-id="searchstax-related-searches-container" id="searchstax-related-searches-container">
Related searches: <span id="searchstax-related-searches"></span>
{{#relatedSearches}}
<span class="searchstax-related-search">
</span>
{{/relatedSearches}}
</div>
{{/hasRelatedSearches}}
`,
relatedSearchesContainerClass: `searchstax-related-search`,
},
relatedSearch: {
template: `
<span class="searchstax-related-search searchstax-related-search-item" data-test-id="searchstax-related-search-item" aria-label="Related search: {{related_search}}" tabindex="0">
{{ related_search }}{{^last}}<span>,</span>{{/last}}
</span>
`,
relatedSearchContainerClass: `searchstax-related-search-item`,
},
},
});ExternalPromotions widget
SearchStax Site Search solution’s External Promotions Widget displays external promotions for UX-JS.
Usage
searchstax.addExternalPromotionsWidget("searchstax-external-promotions-layout-container", {})Props
- templates - see examples below
Main Template Override
Main template for external promotions.
It receives following props:
- hasExternalPromotions - boolean, true if has external promotions
External promotion Template Override
Template for external promotion item.
It receives following props:
- url - url of external promotion
- uniqueId - unique id
- name - name of promotion
- description - description
Example
searchstax.addExternalPromotionsWidget("searchstax-external-promotions-layout-container", {
templates: {
mainTemplate: {
template: `
{{#hasExternalPromotions}}
<div class="searchstax-external-promotions-container" id="searchstax-external-promotions-container" data-test-id="searchstax-external-promotions-container">
External promotions go here
</div>
{{/hasExternalPromotions}}
`,
externalPromotionsContainerId: `searchstax-external-promotions-container`,
},
externalPromotion: {
template: `
<div class="searchstax-external-promotion searchstax-search-result" data-test-id="searchstax-external-promotion">
<div class="icon-elevated"></div>
{{#url}}
<a href="{{url}}" data-searchstax-unique-result-id="{{uniqueId}}" class="searchstax-result-item-link" data-test-id="searchstax-result-item-link"></a>
{{/url}}
<div class="searchstax-search-result-title-container">
<span class="searchstax-search-result-title" data-test-id="searchstax-search-result-title">{{name}}</span>
</div>
{{#description}}
<p class="searchstax-search-result-description searchstax-search-result-common" data-test-id="searchstax-search-result-description">
{{description}}
</p>
{{/description}}
{{#url}}
<p class="searchstax-search-result-description searchstax-search-result-common">
{{url}}
</p>
{{/url}}
</div>
`,
},
},
});Sorting Widget
The SearchStax Site Search solution’s Sorting Widget allows sorting of search results for UX-JS.
Usage
searchstax.addSearchSortingWidget("search-sorting-container", {});Props
- templates - see examples below
Main Template Override
Main template for sorting widget.
It receives following props:
- searchExecuted - boolean, true if search was executed
- hasResultsOrExternalPromotions - boolean, true if there are results or external promotions
- sortOptions - array of sort options, has key/value
Example
searchstax.addSearchSortingWidget("search-sorting-container", {
templates: {
main: {
template: `
{{#searchExecuted}}
{{#hasResultsOrExternalPromotions}}
<div class="searchstax-sorting-container" data-test-id="searchstax-sorting-container">
<label class="searchstax-sorting-label" data-test-id="searchstax-sorting-label" for="searchstax-search-order-select">Sort By</label>
<select id="searchstax-search-order-select" class="searchstax-search-order-select" data-test-id="searchstax-search-order-select" >
{{#sortOptions}}
<option value="{{key}}">
{{value}}
</option>
{{/sortOptions}}
</select>
</div>
{{/hasResultsOrExternalPromotions}}
{{/searchExecuted}}
`,
selectId: `searchstax-search-order-select`
}
},
});Template overrides
Templates use mustache templating. For more info see https://github.com/janl/mustache.js
STYLING
scss styles can be imported from searchstudio-ux-js
@import './../node_modules/@searchstax-inc/searchstudio-ux-js/dist/styles/scss/mainTheme.scss';css can be taken from
./../node_modules/@searchstax-inc/searchstudio-ux-js/dist/styles/mainTheme.cssData Flow Subscriptions
All variables are observables that have these functions:
$observable.subscribe((var) => {})
$observable.setValue(value)
$observable.getValue()Loading change subscription
subscribing to loading event observable is available at
searchstax.dataLayer.$loadingChange.subscribe((data) => {})
searchstax.dataLayer.$loadingChange.setValue(data)
const data = searchstax.dataLayer.$loadingChange.getValue()$loadingChange observable is of type: boolean
Search metadata subscription
subscribing to search metadata event observable is available at
searchstax.dataLayer.$searchResultsMetadata.subscribe((data) => {})
searchstax.dataLayer.$searchResultsMetadata.setValue(data)
const data = searchstax.dataLayer.$searchResultsMetadata.getValue()$searchResultsMetadata observable is of type: ISearchstaxSearchMetadata and can be used for custom pagination implementation along with afterSearch hook
Search pagination data subscription
subscribing to pagination data event observable is available at
searchstax.dataLayer.$paginationData.subscribe((data) => {})
searchstax.dataLayer.$paginationData.setValue(data)
const data = searchstax.dataLayer.$paginationData.getValue()$paginationData observable is of type: IPaginationData and can be used for custom pagination implementation along with afterSearch hook
Data Calculations
At any moment data calculation object is accessible with various variables aimed to help build templates in a cleaner way.
Data calculations
Data calculations can be accessed through
searchstax.dataLayer.parsedData.dataparsedData.data is of type: ISearchstaxParsedData
