@searchstax-inc/searchstudio-ux-vue 0.0.13 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +599 -121
- package/dist/@searchstax-inc/components/SearchstaxExternalPromotionsWidget.vue.d.ts +11 -0
- package/dist/@searchstax-inc/components/SearchstaxExternalPromotionsWidget.vue.d.ts.map +1 -0
- package/dist/@searchstax-inc/components/SearchstaxFacetsWidget.vue.d.ts +7818 -0
- package/dist/@searchstax-inc/components/SearchstaxFacetsWidget.vue.d.ts.map +1 -0
- package/dist/@searchstax-inc/components/SearchstaxInputWidget.vue.d.ts +10 -19
- package/dist/@searchstax-inc/components/SearchstaxInputWidget.vue.d.ts.map +1 -1
- package/dist/@searchstax-inc/components/SearchstaxPaginationWidget.vue.d.ts +14 -0
- package/dist/@searchstax-inc/components/SearchstaxPaginationWidget.vue.d.ts.map +1 -0
- package/dist/@searchstax-inc/components/SearchstaxRelatedSearchesWidget.vue.d.ts +30 -0
- package/dist/@searchstax-inc/components/SearchstaxRelatedSearchesWidget.vue.d.ts.map +1 -0
- package/dist/@searchstax-inc/components/SearchstaxResultWidget.vue.d.ts +7667 -19
- package/dist/@searchstax-inc/components/SearchstaxResultWidget.vue.d.ts.map +1 -1
- package/dist/@searchstax-inc/components/SearchstaxSearchFeedbackWidget.vue.d.ts +11 -0
- package/dist/@searchstax-inc/components/SearchstaxSearchFeedbackWidget.vue.d.ts.map +1 -0
- package/dist/@searchstax-inc/components/SearchstaxSortingWidget.vue.d.ts +12 -0
- package/dist/@searchstax-inc/components/SearchstaxSortingWidget.vue.d.ts.map +1 -0
- package/dist/@searchstax-inc/components/SearchstaxWrapper.vue.d.ts +36 -0
- package/dist/@searchstax-inc/components/SearchstaxWrapper.vue.d.ts.map +1 -1
- package/dist/@searchstax-inc/main.d.ts +7 -1
- package/dist/@searchstax-inc/searchstudio-ux-vue.cjs +213 -61
- package/dist/@searchstax-inc/searchstudio-ux-vue.d.cts +7 -1
- package/dist/@searchstax-inc/searchstudio-ux-vue.d.mts +7 -1
- package/dist/@searchstax-inc/searchstudio-ux-vue.iife.js +213 -61
- package/dist/@searchstax-inc/searchstudio-ux-vue.mjs +2710 -647
- package/dist/@searchstax-inc/stores/searchstaxStore.d.ts +7665 -17
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -3,9 +3,8 @@
|
|
|
3
3
|
Library to build searchstudio search page
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
|
-
npm install following
|
|
6
|
+
npm install following package
|
|
7
7
|
`npm install --save @searchstax-inc/searchstudio-ux-vue`
|
|
8
|
-
`npm install --save @searchstax-inc/searchstudio-ux-js`
|
|
9
8
|
|
|
10
9
|
Add following code to `<head>`
|
|
11
10
|
|
|
@@ -22,98 +21,150 @@ Add following code to `<head>`
|
|
|
22
21
|
})();
|
|
23
22
|
</script>
|
|
24
23
|
```
|
|
24
|
+
## Usage
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
types can be imported from
|
|
28
|
-
|
|
29
|
-
`import type { ISearchstaxParsedResult, ISearchstaxSearchProps, ISearchstaxSuggestProps, ISearchstaxSuggestResponse, Searchstax } from '@searchstax-inc/searchstudio-ux-js'`
|
|
26
|
+
After importing SearchstaxWrapper component needs to wrap all other components:
|
|
30
27
|
|
|
31
|
-
|
|
28
|
+
```
|
|
32
29
|
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
<SearchstaxWrapper
|
|
31
|
+
:language="sampleConfig.language"
|
|
32
|
+
:searchURL="sampleConfig.searchURL"
|
|
33
|
+
:suggesterURL="sampleConfig.suggesterURL"
|
|
34
|
+
:trackApiKey="sampleConfig.trackApiKey"
|
|
35
|
+
:searchAuth="sampleConfig.searchAuth"
|
|
36
|
+
:authType="sampleConfig.authType"
|
|
37
|
+
:router="sampleConfig.router"
|
|
38
|
+
:beforeSearch="sampleConfig.hooks.beforeSearch" // callback function to intercept search object before search is fired
|
|
39
|
+
:afterSearch="sampleConfig.hooks.afterSearch" // callback function to handle results after search is fired
|
|
35
40
|
|
|
36
|
-
|
|
41
|
+
>
|
|
42
|
+
// other components will go there
|
|
37
43
|
|
|
38
|
-
|
|
39
|
-
SearchstaxWrapper
|
|
40
|
-
SearchstaxInputWidget
|
|
41
|
-
SearchstaxResultWidget
|
|
44
|
+
</SearchstaxWrapper>
|
|
42
45
|
```
|
|
43
46
|
|
|
44
47
|
## Initialization
|
|
45
|
-
|
|
46
|
-
```
|
|
47
|
-
const config = {
|
|
48
|
-
searchURL: '', // - SeachStudio select endpoint
|
|
49
|
-
suggesterURL: '', // - SeachStudio suggest endpoint
|
|
50
|
-
trackApiKey: '', // - Api key used for tracking events
|
|
51
|
-
searchAuth: '', // - Authentication value. based on authType it's either a token value or basic auth value
|
|
52
|
-
authType: '', // - Type of authentication
|
|
53
|
-
}
|
|
48
|
+
Initialization object needs to be of type: [ISearchstaxConfig](https://github.com/searchstax/searchstudio-ux-js/blob/main/src/interfaces/connector.interface.ts#L5)
|
|
54
49
|
|
|
55
|
-
|
|
56
|
-
function initialized(searchstax: Searchstax){ // - optional function that returns an instance of Searchstax class. can be used for advanced workflows
|
|
57
|
-
|
|
58
|
-
}
|
|
50
|
+
Initialization example
|
|
59
51
|
```
|
|
60
|
-
|
|
61
|
-
|
|
52
|
+
sampleConfig = {
|
|
53
|
+
language: "en",
|
|
54
|
+
searchURL: "",
|
|
55
|
+
suggesterURL: "",
|
|
56
|
+
trackApiKey: "",
|
|
57
|
+
searchAuth: "",
|
|
58
|
+
authType: "basic",
|
|
59
|
+
router: {
|
|
60
|
+
enabled: true,
|
|
61
|
+
routeName: "searchstax",
|
|
62
|
+
title: (result: ISearchObject) => {
|
|
63
|
+
return "Search results for: " + result.query;
|
|
64
|
+
},
|
|
65
|
+
ignoredKeys: [],
|
|
66
|
+
},
|
|
67
|
+
hooks: {
|
|
68
|
+
beforeSearch: function (props: ISearchObject) {
|
|
69
|
+
const propsCopy = { ...props };
|
|
70
|
+
return propsCopy;
|
|
71
|
+
},
|
|
72
|
+
afterSearch: function (results: ISearchstaxParsedResult[]) {
|
|
73
|
+
const copy = [...results];
|
|
74
|
+
return copy;
|
|
75
|
+
},
|
|
76
|
+
}
|
|
77
|
+
};
|
|
62
78
|
```
|
|
63
79
|
|
|
80
|
+
## Initial layout
|
|
81
|
+
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.
|
|
82
|
+
```
|
|
64
83
|
<SearchstaxWrapper
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
84
|
+
:language="sampleConfig.language"
|
|
85
|
+
:searchURL="sampleConfig.searchURL"
|
|
86
|
+
:suggesterURL="sampleConfig.suggesterURL"
|
|
87
|
+
:trackApiKey="sampleConfig.trackApiKey"
|
|
88
|
+
:searchAuth="sampleConfig.searchAuth"
|
|
89
|
+
:authType="sampleConfig.authType"
|
|
90
|
+
:router="sampleConfig.router"
|
|
91
|
+
:beforeSearch="sampleConfig.hooks.beforeSearch" // callback function to intercept search object before search is fired
|
|
92
|
+
:afterSearch="sampleConfig.hooks.afterSearch" // callback function to handle results after search is fired
|
|
93
|
+
>
|
|
72
94
|
<template #default>
|
|
73
|
-
|
|
95
|
+
<div class="searchstax-page-layout-container">
|
|
96
|
+
<SearchstaxInputWidget
|
|
97
|
+
:afterAutosuggest="afterAutosuggest"
|
|
98
|
+
:beforeAutosuggest="beforeAutosuggest"
|
|
99
|
+
:suggestAfterMinChars="3"
|
|
100
|
+
>
|
|
101
|
+
</SearchstaxInputWidget>
|
|
102
|
+
<div class="search-details-container">
|
|
103
|
+
<SearchstaxSearchFeedbackWidget></SearchstaxSearchFeedbackWidget>
|
|
104
|
+
<SearchstaxSortingWidget></SearchstaxSortingWidget>
|
|
105
|
+
</div>
|
|
106
|
+
<div class="searchstax-page-layout-facet-result-container">
|
|
107
|
+
<div class="searchstax-page-layout-facet-container">
|
|
108
|
+
<SearchstaxFacetsWidget
|
|
109
|
+
:facetingType="'or'"
|
|
110
|
+
:itemsPerPageDesktop="3"
|
|
111
|
+
:itemsPerPageMobile="99"
|
|
112
|
+
>
|
|
113
|
+
</SearchstaxFacetsWidget>
|
|
114
|
+
</div>
|
|
115
|
+
<div class="searchstax-page-layout-result-container">
|
|
116
|
+
<div id="searchstax-external-promotions-layout-container"></div>
|
|
117
|
+
<SearchstaxResultWidget :afterLinkClick="afterLinkClick">
|
|
118
|
+
</SearchstaxResultWidget>
|
|
119
|
+
<div id="searchstax-related-searches-container"></div>
|
|
120
|
+
<SearchstaxPaginationWidget>
|
|
121
|
+
</SearchstaxPaginationWidget>
|
|
122
|
+
</div>
|
|
123
|
+
</div>
|
|
124
|
+
</div>
|
|
74
125
|
</template>
|
|
75
|
-
</SearchstaxWrapper>
|
|
76
|
-
|
|
126
|
+
</SearchstaxWrapper>
|
|
77
127
|
```
|
|
78
128
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
return copy
|
|
96
|
-
}
|
|
97
|
-
function beforeAutosuggest(props: ISearchstaxSuggestProps) {
|
|
98
|
-
// - this function gets called after autosuggest has values but before rendering. It needs to return same type of data but it can be modified.
|
|
99
|
-
const propsCopy = { ...props }
|
|
100
|
-
return propsCopy
|
|
101
|
-
}
|
|
129
|
+
### widgets
|
|
130
|
+
Following widgets are available:
|
|
131
|
+
|
|
132
|
+
[Input Widget](#input-widget)
|
|
133
|
+
|
|
134
|
+
[Result Widget](#result-widget)
|
|
135
|
+
|
|
136
|
+
[Facets Widget](#facets-widget)
|
|
137
|
+
|
|
138
|
+
[Pagination Widget](#pagination-widget)
|
|
139
|
+
|
|
140
|
+
[SearchFeedback Widget](#searchfeedback-widget)
|
|
141
|
+
|
|
142
|
+
[RelatedSearches Widget](#relatedsearches-widget)
|
|
143
|
+
|
|
144
|
+
[ExternalPromotions Widget](#externalpromotions-widget)
|
|
102
145
|
|
|
103
|
-
|
|
146
|
+
[sorting Widget](#sorting-widget)
|
|
147
|
+
|
|
148
|
+
### Input Widget ###
|
|
149
|
+
|
|
150
|
+
example of input widget initialization with minimum options
|
|
151
|
+
```
|
|
152
|
+
<SearchstaxInputWidget
|
|
153
|
+
:afterAutosuggest="afterAutosuggest"
|
|
154
|
+
:beforeAutosuggest="beforeAutosuggest"
|
|
155
|
+
:suggestAfterMinChars="3"
|
|
156
|
+
></SearchstaxInputWidget>
|
|
104
157
|
```
|
|
105
158
|
|
|
106
|
-
HTML example with input override
|
|
107
159
|
|
|
160
|
+
example of input widget initialization with template override
|
|
108
161
|
```
|
|
109
162
|
<SearchstaxInputWidget
|
|
110
|
-
:beforeSearch="beforeSearch"
|
|
111
|
-
:afterSearch="afterSearch"
|
|
112
163
|
:afterAutosuggest="afterAutosuggest"
|
|
113
164
|
:beforeAutosuggest="beforeAutosuggest"
|
|
114
|
-
:suggestAfterMinChars="
|
|
165
|
+
:suggestAfterMinChars="3"
|
|
115
166
|
>
|
|
116
|
-
<template #input>
|
|
167
|
+
<template #input="{ suggestions, onMouseLeave, onMouseOver, onMouseClick }">
|
|
117
168
|
<div class="searchstax-search-input-wrapper">
|
|
118
169
|
<input
|
|
119
170
|
type="text"
|
|
@@ -121,81 +172,508 @@ HTML example with input override
|
|
|
121
172
|
class="searchstax-search-input"
|
|
122
173
|
placeholder="SEARCH FOR..."
|
|
123
174
|
/>
|
|
175
|
+
<div
|
|
176
|
+
class="searchstax-autosuggest-container"
|
|
177
|
+
:class="{ 'hidden': suggestions.length === 0 }"
|
|
178
|
+
@mouseleave="onMouseLeave"
|
|
179
|
+
>
|
|
180
|
+
<div
|
|
181
|
+
class="searchstax-autosuggest-item"
|
|
182
|
+
v-for="suggestion in suggestions"
|
|
183
|
+
:key="suggestion.term"
|
|
184
|
+
>
|
|
185
|
+
<div
|
|
186
|
+
class="searchstax-autosuggest-item-term-container"
|
|
187
|
+
v-html="suggestion.term"
|
|
188
|
+
@mouseover="onMouseOver(suggestion)"
|
|
189
|
+
@click.stop="onMouseClick()"
|
|
190
|
+
></div>
|
|
191
|
+
</div>
|
|
192
|
+
</div>
|
|
124
193
|
<button
|
|
125
194
|
class="searchstax-spinner-icon"
|
|
126
195
|
id="searchstax-search-input-action-button"
|
|
127
|
-
|
|
196
|
+
>
|
|
197
|
+
</button>
|
|
128
198
|
</div>
|
|
129
199
|
</template>
|
|
130
200
|
</SearchstaxInputWidget>
|
|
131
201
|
```
|
|
132
|
-
|
|
202
|
+
### Result Widget ###
|
|
133
203
|
|
|
134
|
-
|
|
204
|
+
example of results widget initialization with minimum options
|
|
205
|
+
```
|
|
206
|
+
<SearchstaxResultWidget :afterLinkClick="afterLinkClick"></SearchstaxResultWidget>
|
|
135
207
|
```
|
|
136
|
-
function afterLinkClick(result: ISearchstaxParsedResult) {
|
|
137
|
-
// - function is called after user clicks result and passes that result as a property. when result is passed along tracking will execute and user will be navigated if null is returned events are canceled and nothing happens.
|
|
138
|
-
const propsCopy = { ...result }
|
|
139
208
|
|
|
140
|
-
|
|
141
|
-
|
|
209
|
+
example of result widget initialization with template override
|
|
210
|
+
```
|
|
211
|
+
<SearchstaxResultWidget :afterLinkClick="afterLinkClick">
|
|
212
|
+
<template #results="{ searchResults, resultClicked }">
|
|
213
|
+
<div
|
|
214
|
+
class="searchstax-search-results"
|
|
215
|
+
v-if="searchResults && searchResults.length"
|
|
216
|
+
>
|
|
217
|
+
<div
|
|
218
|
+
class="searchstax-search-result"
|
|
219
|
+
:class="{ 'has-thumbnail': searchResult.thumbnail }"
|
|
220
|
+
:key="searchResult.uniqueId"
|
|
221
|
+
v-for="searchResult in searchResults"
|
|
222
|
+
>
|
|
223
|
+
<div
|
|
224
|
+
v-if="searchResult.promoted"
|
|
225
|
+
class="searchstax-search-result-promoted"
|
|
226
|
+
></div>
|
|
227
|
+
<a
|
|
228
|
+
v-if="searchResult.url"
|
|
229
|
+
:href="searchResult.url"
|
|
230
|
+
:data-searchstax-unique-result-id="searchResult.uniqueId"
|
|
231
|
+
@click="resultClicked(searchResult, $event)"
|
|
232
|
+
class="searchstax-result-item-link"
|
|
233
|
+
></a>
|
|
234
|
+
<div
|
|
235
|
+
v-if="searchResult.ribbon"
|
|
236
|
+
class="searchstax-search-result-ribbon"
|
|
237
|
+
> {{ searchResult.ribbon }} </div>
|
|
238
|
+
<img
|
|
239
|
+
v-if="searchResult.thumbnail"
|
|
240
|
+
:src="searchResult.thumbnail"
|
|
241
|
+
class="searchstax-thumbnail"
|
|
242
|
+
/>
|
|
243
|
+
<div class="searchstax-search-result-title-container">
|
|
244
|
+
<span class="searchstax-search-result-title">{{ searchResult.title }}</span>
|
|
245
|
+
</div>
|
|
246
|
+
<p
|
|
247
|
+
v-if="searchResult.paths"
|
|
248
|
+
class="searchstax-search-result-common"
|
|
249
|
+
> {{ searchResult.paths }} </p>
|
|
250
|
+
<p
|
|
251
|
+
v-if="searchResult.description"
|
|
252
|
+
class="searchstax-search-result-description searchstax-search-result-common"
|
|
253
|
+
> {{ searchResult.description }} </p>
|
|
254
|
+
<div
|
|
255
|
+
:key="unmappedField.key"
|
|
256
|
+
v-for="unmappedField in searchResult.unmappedFields"
|
|
257
|
+
>
|
|
258
|
+
<div
|
|
259
|
+
v-if="unmappedField.isImage && typeof unmappedField.value === 'string'"
|
|
260
|
+
class="searchstax-search-result-image-container"
|
|
261
|
+
>
|
|
262
|
+
<img
|
|
263
|
+
:src="unmappedField.value"
|
|
264
|
+
class="searchstax-result-image"
|
|
265
|
+
/>
|
|
266
|
+
</div>
|
|
267
|
+
<div v-else>
|
|
268
|
+
<p class="searchstax-search-result-common"> {{ unmappedField.value }} </p>
|
|
269
|
+
</div>
|
|
270
|
+
</div>
|
|
271
|
+
</div>
|
|
272
|
+
</div>
|
|
273
|
+
</template>
|
|
274
|
+
</SearchstaxResultWidget>
|
|
142
275
|
```
|
|
143
276
|
|
|
144
|
-
|
|
277
|
+
### Pagination Widget ###
|
|
145
278
|
|
|
279
|
+
|
|
280
|
+
example of pagination widget initialization with minimum options
|
|
281
|
+
```
|
|
282
|
+
<SearchstaxPaginationWidget></SearchstaxPaginationWidget>
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
example of pagination widget initialization with various options
|
|
286
|
+
```
|
|
287
|
+
<template #pagination="{ paginationData, previousPage, nextPage }">
|
|
288
|
+
<div
|
|
289
|
+
class="searchstax-pagination-container"
|
|
290
|
+
v-if="paginationData"
|
|
291
|
+
>
|
|
292
|
+
<div class="searchstax-pagination-content">
|
|
293
|
+
<a
|
|
294
|
+
class="searchstax-pagination-previous"
|
|
295
|
+
:disabled="paginationData?.isFirstPage"
|
|
296
|
+
@click="previousPage"
|
|
297
|
+
id="searchstax-pagination-previous"
|
|
298
|
+
> < Previous </a>
|
|
299
|
+
<div class="searchstax-pagination-details"> {{ paginationData?.startResultIndex }} - {{
|
|
300
|
+
paginationData?.endResultIndex }} of {{ paginationData?.totalResults }} </div>
|
|
301
|
+
<a
|
|
302
|
+
class="searchstax-pagination-next"
|
|
303
|
+
:disabled="paginationData?.isLastPage"
|
|
304
|
+
@click="nextPage"
|
|
305
|
+
id="searchstax-pagination-next"
|
|
306
|
+
>Next ></a>
|
|
307
|
+
</div>
|
|
308
|
+
</div>
|
|
309
|
+
</template>
|
|
146
310
|
```
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
:
|
|
154
|
-
|
|
311
|
+
|
|
312
|
+
### Facets Widget ###
|
|
313
|
+
|
|
314
|
+
example of facets widget initialization with minimum options
|
|
315
|
+
```
|
|
316
|
+
<SearchstaxFacetsWidget
|
|
317
|
+
:facetingType="'or'"
|
|
318
|
+
:itemsPerPageDesktop="3"
|
|
319
|
+
:itemsPerPageMobile="99"
|
|
320
|
+
></SearchstaxFacetsWidget>
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
example of facets widget initialization with template overrides
|
|
325
|
+
```
|
|
326
|
+
<SearchstaxFacetsWidget
|
|
327
|
+
:facetingType="'or'"
|
|
328
|
+
:itemsPerPageDesktop="3"
|
|
329
|
+
:itemsPerPageMobile="99"
|
|
155
330
|
>
|
|
156
|
-
<
|
|
157
|
-
|
|
158
|
-
:href="searchResult.url"
|
|
159
|
-
:data-searchstax-unique-result-id="searchResult.uniqueId"
|
|
160
|
-
@click="resultClicked(searchResult, $event)"
|
|
161
|
-
class="searchstax-result-item-link"
|
|
162
|
-
></a>
|
|
163
|
-
<div v-if="searchResult.ribbon" class="searchstax-search-result-ribbon">
|
|
164
|
-
{{ searchResult.ribbon }}
|
|
165
|
-
</div>
|
|
166
|
-
<img
|
|
167
|
-
v-if="searchResult.thumbnail"
|
|
168
|
-
:src="searchResult.thumbnail"
|
|
169
|
-
class="searchstax-thumbnail"
|
|
170
|
-
/>
|
|
171
|
-
<div class="searchstax-search-result-title-container">
|
|
172
|
-
<span class="searchstax-search-result-title">{{ searchResult.title }}dddd</span>
|
|
173
|
-
</div>
|
|
174
|
-
<p v-if="searchResult.paths" class="searchstax-search-result-common">
|
|
175
|
-
{{ searchResult.paths }}
|
|
176
|
-
</p>
|
|
177
|
-
<p
|
|
178
|
-
v-if="searchResult.description"
|
|
179
|
-
class="searchstax-search-result-description searchstax-search-result-common"
|
|
331
|
+
<template
|
|
332
|
+
#desktopFacets="{ facetsTemplateDataDesktop, isNotDeactivated, toggleFacetGroup, isChecked, selectFacet, showMoreLessDesktop, facetContainers }"
|
|
180
333
|
>
|
|
181
|
-
|
|
182
|
-
|
|
334
|
+
<div
|
|
335
|
+
v-if="facetsTemplateDataDesktop?.hasResultsOrExternalPromotions"
|
|
336
|
+
class="searchstax-facets-container-desktop"
|
|
337
|
+
>
|
|
338
|
+
<div
|
|
339
|
+
v-for="facet in facetsTemplateDataDesktop.facets"
|
|
340
|
+
:key="facet"
|
|
341
|
+
class="searchstax-facet-container"
|
|
342
|
+
:class="{ 'active': isNotDeactivated(facet.name) }"
|
|
343
|
+
>
|
|
344
|
+
<div>
|
|
345
|
+
<div
|
|
346
|
+
class="searchstax-facet-title-container"
|
|
347
|
+
@click="toggleFacetGroup(facet.name)"
|
|
348
|
+
>
|
|
349
|
+
<div class="searchstax-facet-title"> {{ facet.label }} </div>
|
|
350
|
+
<div class="searchstax-facet-title-arrow active"></div>
|
|
351
|
+
</div>
|
|
352
|
+
<div class="searchstax-facet-values-container">
|
|
353
|
+
<div
|
|
354
|
+
v-for="(facetValue, key) in facet.values"
|
|
355
|
+
:key="facetValue.value + facetValue.parentName"
|
|
356
|
+
class="searchstax-facet-value-container"
|
|
357
|
+
:class="{ 'searchstax-facet-value-disabled': facetValue.disabled }"
|
|
358
|
+
:ref="el => { facetContainers[key + facet.name] = el }"
|
|
359
|
+
>
|
|
360
|
+
<div class="searchstax-facet-input">
|
|
361
|
+
<input
|
|
362
|
+
type="checkbox"
|
|
363
|
+
class="searchstax-facet-input-checkbox"
|
|
364
|
+
:checked="isChecked(facetValue)"
|
|
365
|
+
:disabled="facetValue.disabled"
|
|
366
|
+
@click="selectFacet(key + facet.name, $event, facetValue, true)"
|
|
367
|
+
/>
|
|
368
|
+
</div>
|
|
369
|
+
<div
|
|
370
|
+
class="searchstax-facet-value-label"
|
|
371
|
+
@click="selectFacet(key + facet.name, $event, facetValue, false)"
|
|
372
|
+
>{{ facetValue.value }}</div>
|
|
373
|
+
<div
|
|
374
|
+
class="searchstax-facet-value-count"
|
|
375
|
+
@click="selectFacet(key + facet.name, $event, facetValue, false)"
|
|
376
|
+
>({{ facetValue.count }})</div>
|
|
377
|
+
</div>
|
|
378
|
+
<div
|
|
379
|
+
class="searchstax-facet-show-more-container"
|
|
380
|
+
v-if="facet.hasMoreFacets"
|
|
381
|
+
>
|
|
382
|
+
<div
|
|
383
|
+
class="searchstax-facet-show-more-container"
|
|
384
|
+
@click="showMoreLessDesktop($event, facet)"
|
|
385
|
+
>
|
|
386
|
+
<div
|
|
387
|
+
v-if="facet.showingAllFacets"
|
|
388
|
+
class="searchstax-facet-show-less-button searchstax-facet-show-button"
|
|
389
|
+
>less</div>
|
|
390
|
+
<div
|
|
391
|
+
v-else
|
|
392
|
+
class="searchstax-facet-show-more-button searchstax-facet-show-button"
|
|
393
|
+
>more</div>
|
|
394
|
+
</div>
|
|
395
|
+
</div>
|
|
396
|
+
</div>
|
|
397
|
+
</div>
|
|
398
|
+
</div>
|
|
399
|
+
</div>
|
|
400
|
+
</template>
|
|
401
|
+
<template
|
|
402
|
+
#mobileFacets="{ facetsTemplateDataMobile, selectedFacetsCheckboxes, isNotDeactivated, toggleFacetGroup, isChecked, selectFacet, showMoreLessDesktop, facetContainers, openOverlay, unselectFacet, unselectAll, closeOverlay }"
|
|
403
|
+
>
|
|
404
|
+
<div
|
|
405
|
+
class="searchstax-facets-container-mobile"
|
|
406
|
+
v-if="facetsTemplateDataMobile?.hasResultsOrExternalPromotions"
|
|
407
|
+
>
|
|
408
|
+
<div class="searchstax-facets-pills-container">
|
|
409
|
+
<div
|
|
410
|
+
class="searchstax-facets-pill searchstax-facets-pill-filter-by"
|
|
411
|
+
@click="openOverlay"
|
|
412
|
+
>
|
|
413
|
+
<div class="searchstax-facets-pill-label">Filter By</div>
|
|
414
|
+
</div>
|
|
415
|
+
<div class="searchstax-facets-pills-selected">
|
|
416
|
+
<div
|
|
417
|
+
class="searchstax-facets-pill searchstax-facets-pill-facets"
|
|
418
|
+
v-for="facet in selectedFacetsCheckboxes"
|
|
419
|
+
:key="facet.value"
|
|
420
|
+
@click="unselectFacet(facet)"
|
|
421
|
+
>
|
|
422
|
+
<div class="searchstax-facets-pill-label">{{ facet.value }} ({{ facet.count }})</div>
|
|
423
|
+
<div class="searchstax-facets-pill-icon-close"></div>
|
|
424
|
+
</div>
|
|
425
|
+
</div>
|
|
426
|
+
<div
|
|
427
|
+
class="searchstax-facets-pill searchstax-clear-filters searchstax-facets-pill-clear-all"
|
|
428
|
+
v-if="selectedFacetsCheckboxes.length"
|
|
429
|
+
@click="unselectAll"
|
|
430
|
+
>
|
|
431
|
+
<div class="searchstax-facets-pill-label">Clear Filters</div>
|
|
432
|
+
</div>
|
|
433
|
+
</div>
|
|
434
|
+
<div
|
|
435
|
+
class="searchstax-facets-mobile-overlay"
|
|
436
|
+
:class="{ 'searchstax-show': facetsTemplateDataMobile?.overlayOpened }"
|
|
437
|
+
>
|
|
438
|
+
<div class="searchstax-facets-mobile-overlay-header">
|
|
439
|
+
<div class="searchstax-facets-mobile-overlay-header-title">Filter By</div>
|
|
440
|
+
<div
|
|
441
|
+
class="searchstax-search-close"
|
|
442
|
+
@click="closeOverlay"
|
|
443
|
+
></div>
|
|
444
|
+
</div>
|
|
445
|
+
<div class="searchstax-facets-container-mobile">
|
|
446
|
+
<div
|
|
447
|
+
v-for="facet in facetsTemplateDataMobile?.facets"
|
|
448
|
+
:key="facet"
|
|
449
|
+
class="searchstax-facet-container"
|
|
450
|
+
:class="{ 'active': isNotDeactivated(facet.name) }"
|
|
451
|
+
>
|
|
452
|
+
<div>
|
|
453
|
+
<div
|
|
454
|
+
class="searchstax-facet-title-container"
|
|
455
|
+
@click="toggleFacetGroup(facet.name)"
|
|
456
|
+
>
|
|
457
|
+
<div class="searchstax-facet-title"> {{ facet.label }} </div>
|
|
458
|
+
<div class="searchstax-facet-title-arrow active"></div>
|
|
459
|
+
</div>
|
|
460
|
+
<div class="searchstax-facet-values-container">
|
|
461
|
+
<div
|
|
462
|
+
v-for="(facetValue, key) in facet.values"
|
|
463
|
+
:key="facetValue.value + facetValue.parentName"
|
|
464
|
+
class="searchstax-facet-value-container"
|
|
465
|
+
:class="{ 'searchstax-facet-value-disabled': facetValue.disabled }"
|
|
466
|
+
:ref="el => { facetContainers[key + facet.name] = el }"
|
|
467
|
+
>
|
|
468
|
+
<div class="searchstax-facet-input">
|
|
469
|
+
<input
|
|
470
|
+
type="checkbox"
|
|
471
|
+
class="searchstax-facet-input-checkbox"
|
|
472
|
+
:checked="isChecked(facetValue)"
|
|
473
|
+
:disabled="facetValue.disabled"
|
|
474
|
+
@click="selectFacet(key + facet.name, $event, facetValue, true)"
|
|
475
|
+
/>
|
|
476
|
+
</div>
|
|
477
|
+
<div
|
|
478
|
+
class="searchstax-facet-value-label"
|
|
479
|
+
@click="selectFacet(key + facet.name, $event, facetValue, false)"
|
|
480
|
+
>{{ facetValue.value }}</div>
|
|
481
|
+
<div
|
|
482
|
+
class="searchstax-facet-value-count"
|
|
483
|
+
@click="selectFacet(key + facet.name, $event, facetValue, false)"
|
|
484
|
+
>({{ facetValue.count }})</div>
|
|
485
|
+
</div>
|
|
486
|
+
<div
|
|
487
|
+
class="searchstax-facet-show-more-container"
|
|
488
|
+
v-if="facet.hasMoreFacets"
|
|
489
|
+
>
|
|
490
|
+
<div
|
|
491
|
+
class="searchstax-facet-show-more-container"
|
|
492
|
+
@click="showMoreLessDesktop($event, facet)"
|
|
493
|
+
>
|
|
494
|
+
<div
|
|
495
|
+
v-if="facet.showingAllFacets"
|
|
496
|
+
class="searchstax-facet-show-less-button searchstax-facet-show-button"
|
|
497
|
+
>less</div>
|
|
498
|
+
<div
|
|
499
|
+
v-else
|
|
500
|
+
class="searchstax-facet-show-more-button searchstax-facet-show-button"
|
|
501
|
+
>more</div>
|
|
502
|
+
</div>
|
|
503
|
+
</div>
|
|
504
|
+
</div>
|
|
505
|
+
</div>
|
|
506
|
+
</div>
|
|
507
|
+
</div>
|
|
508
|
+
<button
|
|
509
|
+
class="searchstax-facets-mobile-overlay-done"
|
|
510
|
+
@click="closeOverlay"
|
|
511
|
+
>Done</button>
|
|
512
|
+
</div>
|
|
513
|
+
</div>
|
|
514
|
+
</template>
|
|
515
|
+
</SearchstaxFacetsWidget>
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
### SearchFeedback Widget ###
|
|
519
|
+
|
|
520
|
+
example of search feedback widget initialization with minimum options
|
|
521
|
+
```
|
|
522
|
+
<SearchstaxSearchFeedbackWidget></SearchstaxSearchFeedbackWidget>
|
|
523
|
+
```
|
|
524
|
+
|
|
183
525
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
526
|
+
example of search feedback widget initialization with template overrides
|
|
527
|
+
```
|
|
528
|
+
<SearchstaxSearchFeedbackWidget>
|
|
529
|
+
<template #searchFeedback="{ searchFeedbackData, onOriginalQueryClick }">
|
|
530
|
+
<div
|
|
531
|
+
class="searchstax-feedback-container"
|
|
532
|
+
v-if="searchFeedbackData && searchFeedbackData?.searchExecuted"
|
|
533
|
+
> Showing <b>{{ searchFeedbackData.startResultIndex }} - {{ searchFeedbackData.endResultIndex }}</b> of
|
|
534
|
+
<b>{{ searchFeedbackData.totalResults }}</b> results <span v-if="searchFeedbackData.searchTerm">for "<b>{{
|
|
535
|
+
searchFeedbackData.searchTerm }}</b>" </span>
|
|
536
|
+
<div class="searchstax-feedback-container-suggested">
|
|
537
|
+
<div v-if="searchFeedbackData.autoCorrectedQuery"> Search instead for <a
|
|
538
|
+
href="#"
|
|
539
|
+
@click.prevent="onOriginalQueryClick($event)"
|
|
540
|
+
class="searchstax-feedback-original-query"
|
|
541
|
+
>{{ searchFeedbackData.originalQuery }}</a>
|
|
542
|
+
</div>
|
|
187
543
|
</div>
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
544
|
+
</div>
|
|
545
|
+
</template>
|
|
546
|
+
</SearchstaxSearchFeedbackWidget>
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
## RelatedSearches widget
|
|
550
|
+
|
|
551
|
+
|
|
552
|
+
|
|
553
|
+
example of search feedback widget initialization with minimum options
|
|
554
|
+
```
|
|
555
|
+
<SearchstaxRelatedSearchesWidget
|
|
556
|
+
:relatedSearchesURL="config.relatedSearchesURL"
|
|
557
|
+
:relatedSearchesAPIKey="config.relatedSearchesAPIKey"
|
|
558
|
+
></SearchstaxRelatedSearchesWidget>
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
example of search feedback widget initialization with template overrides
|
|
563
|
+
```
|
|
564
|
+
<SearchstaxRelatedSearchesWidget
|
|
565
|
+
:relatedSearchesURL="config.relatedSearchesURL"
|
|
566
|
+
:relatedSearchesAPIKey="config.relatedSearchesAPIKey"
|
|
567
|
+
>
|
|
568
|
+
<template #related="{ relatedData, executeSearch }">
|
|
569
|
+
<div
|
|
570
|
+
class="searchstax-related-searches-container"
|
|
571
|
+
id="searchstax-related-searches-container"
|
|
572
|
+
v-if="relatedData && relatedData?.searchExecuted && relatedData?.hasRelatedSearches"
|
|
573
|
+
> Related searches: <span id="searchstax-related-searches"></span>
|
|
574
|
+
<span
|
|
575
|
+
class="searchstax-related-search"
|
|
576
|
+
v-if="relatedData.relatedSearches"
|
|
577
|
+
>
|
|
578
|
+
<span
|
|
579
|
+
v-for="related in relatedData.relatedSearches"
|
|
580
|
+
:key="related.related_search"
|
|
581
|
+
@click="executeSearch(related)"
|
|
582
|
+
class="searchstax-related-search searchstax-related-search-item"
|
|
583
|
+
> {{ related.related_search }}<span v-if="!related.last">,</span>
|
|
584
|
+
</span>
|
|
585
|
+
</span>
|
|
586
|
+
</div>
|
|
587
|
+
</template>
|
|
588
|
+
</SearchstaxRelatedSearchesWidget>
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
### ExternalPromotions widget ###
|
|
592
|
+
|
|
593
|
+
example of search feedback widget initialization with minimum options
|
|
594
|
+
```
|
|
595
|
+
<SearchstaxExternalPromotionsWidget></SearchstaxExternalPromotionsWidget>
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
|
|
599
|
+
example of search feedback widget initialization with template overrides
|
|
600
|
+
```
|
|
601
|
+
<SearchstaxExternalPromotionsWidget>
|
|
602
|
+
<template #externalPromotions="{ externalPromotionsData, trackClick }">
|
|
603
|
+
<div
|
|
604
|
+
class="searchstax-external-promotions-container"
|
|
605
|
+
id="searchstax-external-promotions-container"
|
|
606
|
+
v-if="externalPromotionsData && externalPromotionsData?.searchExecuted && externalPromotionsData?.hasExternalPromotions"
|
|
607
|
+
>
|
|
608
|
+
<div
|
|
609
|
+
class="searchstax-external-promotion searchstax-search-result"
|
|
610
|
+
v-for="externalPromotion in externalPromotionsData.externalPromotions"
|
|
611
|
+
:key="externalPromotion.id"
|
|
612
|
+
>
|
|
613
|
+
<div class="icon-elevated"></div>
|
|
614
|
+
<a
|
|
615
|
+
v-if="externalPromotion.url"
|
|
616
|
+
href="{{externalPromotion.url}}"
|
|
617
|
+
@click="trackClick(externalPromotion, $event)"
|
|
618
|
+
class="searchstax-result-item-link"
|
|
619
|
+
></a>
|
|
620
|
+
<div class="searchstax-search-result-title-container">
|
|
621
|
+
<span class="searchstax-search-result-title">{{ externalPromotion.name }}</span>
|
|
622
|
+
</div>
|
|
623
|
+
<p
|
|
624
|
+
v-if="externalPromotion.description"
|
|
625
|
+
class="searchstax-search-result-description searchstax-search-result-common"
|
|
626
|
+
> {{ externalPromotion.description }} </p>
|
|
627
|
+
<p
|
|
628
|
+
v-if="externalPromotion.url"
|
|
629
|
+
class="searchstax-search-result-description searchstax-search-result-common"
|
|
630
|
+
> {{ externalPromotion.url }} </p>
|
|
631
|
+
</div>
|
|
192
632
|
</div>
|
|
633
|
+
</template>
|
|
634
|
+
</SearchstaxExternalPromotionsWidget>
|
|
635
|
+
```
|
|
636
|
+
|
|
637
|
+
|
|
638
|
+
### Sorting Widget ###
|
|
639
|
+
|
|
640
|
+
example of sorting widget initialization with minimum options
|
|
641
|
+
```
|
|
642
|
+
<SearchstaxSortingWidget></SearchstaxSortingWidget>
|
|
643
|
+
```
|
|
644
|
+
|
|
645
|
+
|
|
646
|
+
example of sorting widget initialization with template override
|
|
647
|
+
```
|
|
648
|
+
<SearchstaxSortingWidget>
|
|
649
|
+
<template #sorting="{ sortingData, orderChange, selectedSorting }">
|
|
650
|
+
<div
|
|
651
|
+
class="searchstax-sorting-container"
|
|
652
|
+
v-if="sortingData && sortingData?.searchExecuted && sortingData?.hasResultsOrExternalPromotions"
|
|
653
|
+
>
|
|
654
|
+
<label
|
|
655
|
+
class="searchstax-sorting-label"
|
|
656
|
+
for="sort-by"
|
|
657
|
+
>Sort By</label>
|
|
658
|
+
<select
|
|
659
|
+
id="searchstax-search-order-select"
|
|
660
|
+
class="searchstax-search-order-select"
|
|
661
|
+
:value="selectedSorting"
|
|
662
|
+
@change="orderChange($event)"
|
|
663
|
+
>
|
|
664
|
+
<option value=""> Relevance </option>
|
|
665
|
+
<option value="date desc"> Newest Content </option>
|
|
666
|
+
<option value="date asc"> Oldest Content </option>
|
|
667
|
+
</select>
|
|
193
668
|
</div>
|
|
194
|
-
</
|
|
195
|
-
</
|
|
196
|
-
</SearchstaxResultWidget>
|
|
669
|
+
</template>
|
|
670
|
+
</SearchstaxSortingWidget>
|
|
197
671
|
```
|
|
198
672
|
|
|
673
|
+
|
|
674
|
+
## Template overrides
|
|
675
|
+
Templates use vue slots.
|
|
676
|
+
|
|
199
677
|
## STYLING
|
|
200
678
|
|
|
201
679
|
scss styles can be imported from searchstudio-ux-js
|