@searchspring/snap-controller 0.65.1 → 0.66.0
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/dist/cjs/Autocomplete/AutocompleteController.d.ts +2 -1
- package/dist/cjs/Autocomplete/AutocompleteController.d.ts.map +1 -1
- package/dist/cjs/Autocomplete/AutocompleteController.js +79 -32
- package/dist/cjs/Recommendation/RecommendationController.d.ts +2 -3
- package/dist/cjs/Recommendation/RecommendationController.d.ts.map +1 -1
- package/dist/cjs/Recommendation/RecommendationController.js +73 -25
- package/dist/cjs/Search/SearchController.d.ts +1 -1
- package/dist/cjs/Search/SearchController.d.ts.map +1 -1
- package/dist/cjs/Search/SearchController.js +141 -61
- package/dist/cjs/utils/isClickWithinProductLink.d.ts +5 -0
- package/dist/cjs/utils/isClickWithinProductLink.d.ts.map +1 -0
- package/dist/cjs/utils/isClickWithinProductLink.js +22 -0
- package/dist/esm/Autocomplete/AutocompleteController.d.ts +2 -1
- package/dist/esm/Autocomplete/AutocompleteController.d.ts.map +1 -1
- package/dist/esm/Autocomplete/AutocompleteController.js +66 -28
- package/dist/esm/Recommendation/RecommendationController.d.ts +2 -3
- package/dist/esm/Recommendation/RecommendationController.d.ts.map +1 -1
- package/dist/esm/Recommendation/RecommendationController.js +56 -23
- package/dist/esm/Search/SearchController.d.ts +1 -1
- package/dist/esm/Search/SearchController.d.ts.map +1 -1
- package/dist/esm/Search/SearchController.js +123 -53
- package/dist/esm/utils/isClickWithinProductLink.d.ts +5 -0
- package/dist/esm/utils/isClickWithinProductLink.d.ts.map +1 -0
- package/dist/esm/utils/isClickWithinProductLink.js +17 -0
- package/package.json +10 -10
|
@@ -81,6 +81,7 @@ var AbstractController_1 = require("../Abstract/AbstractController");
|
|
|
81
81
|
var snap_store_mobx_1 = require("@searchspring/snap-store-mobx");
|
|
82
82
|
var getParams_1 = require("../utils/getParams");
|
|
83
83
|
var types_1 = require("../types");
|
|
84
|
+
var isClickWithinProductLink_1 = require("../utils/isClickWithinProductLink");
|
|
84
85
|
var BACKGROUND_FILTER_FIELD_MATCHES = ['collection', 'category', 'categories', 'hierarchy'];
|
|
85
86
|
var BACKGROUND_FILTERS_VALUE_FLAGS = [1, 0, '1', '0', 'true', 'false', true, false];
|
|
86
87
|
var defaultConfig = {
|
|
@@ -99,6 +100,7 @@ var defaultConfig = {
|
|
|
99
100
|
},
|
|
100
101
|
},
|
|
101
102
|
};
|
|
103
|
+
var schemaMap = {};
|
|
102
104
|
var SearchController = /** @class */ (function (_super) {
|
|
103
105
|
__extends(SearchController, _super);
|
|
104
106
|
function SearchController(config, _a, context) {
|
|
@@ -142,56 +144,57 @@ var SearchController = /** @class */ (function (_super) {
|
|
|
142
144
|
}
|
|
143
145
|
// store position data or empty object
|
|
144
146
|
_this.storage.set('scrollMap', scrollMap);
|
|
145
|
-
var data =
|
|
147
|
+
var data = schemaMap[result.id];
|
|
146
148
|
_this.tracker.events[_this.pageType].clickThrough({ data: data, siteId: (_f = _this.config.globals) === null || _f === void 0 ? void 0 : _f.siteId });
|
|
147
149
|
_this.events.product[result.id] = _this.events.product[result.id] || {};
|
|
148
150
|
_this.events.product[result.id].clickThrough = true;
|
|
149
|
-
_this.eventManager.fire('track.product.clickThrough', { controller: _this, event: e,
|
|
151
|
+
_this.eventManager.fire('track.product.clickThrough', { controller: _this, event: e, product: result, trackEvent: data });
|
|
150
152
|
},
|
|
151
153
|
click: function (e, result) {
|
|
152
|
-
var _a
|
|
153
|
-
if (result.
|
|
154
|
+
var _a;
|
|
155
|
+
if ((_a = _this.events.product[result.id]) === null || _a === void 0 ? void 0 : _a.click) {
|
|
154
156
|
return;
|
|
155
157
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
if (href) {
|
|
159
|
-
_this.track.product.clickThrough(e, result);
|
|
160
|
-
}
|
|
161
|
-
else {
|
|
162
|
-
// TODO: in future, send as an interaction event
|
|
158
|
+
if (result.type === 'banner') {
|
|
159
|
+
return;
|
|
163
160
|
}
|
|
161
|
+
(0, isClickWithinProductLink_1.isClickWithinProductLink)(e, result) && _this.track.product.clickThrough(e, result);
|
|
162
|
+
_this.events.product[result.id] = _this.events.product[result.id] || {};
|
|
163
|
+
_this.events.product[result.id].click = true;
|
|
164
|
+
setTimeout(function () {
|
|
165
|
+
_this.events.product[result.id].click = false;
|
|
166
|
+
}, isClickWithinProductLink_1.CLICK_DUPLICATION_TIMEOUT);
|
|
164
167
|
},
|
|
165
168
|
render: function (result) {
|
|
166
169
|
var _a, _b;
|
|
167
170
|
if ((_a = _this.events.product[result.id]) === null || _a === void 0 ? void 0 : _a.render) {
|
|
168
171
|
return;
|
|
169
172
|
}
|
|
170
|
-
var data =
|
|
173
|
+
var data = schemaMap[result.id];
|
|
171
174
|
_this.tracker.events[_this.pageType].render({ data: data, siteId: (_b = _this.config.globals) === null || _b === void 0 ? void 0 : _b.siteId });
|
|
172
175
|
_this.events.product[result.id] = _this.events.product[result.id] || {};
|
|
173
176
|
_this.events.product[result.id].render = true;
|
|
174
|
-
_this.eventManager.fire('track.product.render', { controller: _this,
|
|
177
|
+
_this.eventManager.fire('track.product.render', { controller: _this, product: result, trackEvent: data });
|
|
175
178
|
},
|
|
176
179
|
impression: function (result) {
|
|
177
180
|
var _a, _b;
|
|
178
181
|
if ((_a = _this.events.product[result.id]) === null || _a === void 0 ? void 0 : _a.impression) {
|
|
179
182
|
return;
|
|
180
183
|
}
|
|
181
|
-
var data =
|
|
184
|
+
var data = schemaMap[result.id];
|
|
182
185
|
_this.tracker.events[_this.pageType].impression({ data: data, siteId: (_b = _this.config.globals) === null || _b === void 0 ? void 0 : _b.siteId });
|
|
183
186
|
_this.events.product[result.id] = _this.events.product[result.id] || {};
|
|
184
187
|
_this.events.product[result.id].impression = true;
|
|
185
|
-
_this.eventManager.fire('track.product.impression', { controller: _this,
|
|
188
|
+
_this.eventManager.fire('track.product.impression', { controller: _this, product: result, trackEvent: data });
|
|
186
189
|
},
|
|
187
190
|
addToCart: function (result) {
|
|
188
191
|
var _a;
|
|
189
|
-
var data =
|
|
192
|
+
var data = getSearchAddtocartSchemaData({ searchSchemaData: schemaMap[result.id], results: [result] });
|
|
190
193
|
_this.tracker.events[_this.pageType].addToCart({
|
|
191
194
|
data: data,
|
|
192
195
|
siteId: (_a = _this.config.globals) === null || _a === void 0 ? void 0 : _a.siteId,
|
|
193
196
|
});
|
|
194
|
-
_this.eventManager.fire('track.product.addToCart', { controller: _this,
|
|
197
|
+
_this.eventManager.fire('track.product.addToCart', { controller: _this, product: result, trackEvent: data });
|
|
195
198
|
},
|
|
196
199
|
},
|
|
197
200
|
redirect: function (redirectURL) {
|
|
@@ -202,7 +205,7 @@ var SearchController = /** @class */ (function (_super) {
|
|
|
202
205
|
},
|
|
203
206
|
};
|
|
204
207
|
_this.search = function () { return __awaiter(_this, void 0, void 0, function () {
|
|
205
|
-
var params_1, err_1, stringyParams, prevStringyParams, searchProfile, meta, response, preventBackfill, dontBackfill, backfillRequests, backfillResponses, backfillResults, afterSearchProfile, err_2, afterStoreProfile, err_3, err_4;
|
|
208
|
+
var params_1, err_1, stringyParams, prevStringyParams, searchProfile, meta, response, preventBackfill, dontBackfill, backfillRequestsParams_1, backfillRequests, backfillResponses, backfillResults, afterSearchProfile, err_2, afterStoreProfile, err_3, err_4;
|
|
206
209
|
var _a, _b;
|
|
207
210
|
var _this = this;
|
|
208
211
|
var _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
@@ -244,7 +247,7 @@ var SearchController = /** @class */ (function (_super) {
|
|
|
244
247
|
}
|
|
245
248
|
return [3 /*break*/, 6];
|
|
246
249
|
case 6:
|
|
247
|
-
stringyParams = JSON.stringify(params_1);
|
|
250
|
+
stringyParams = JSON.stringify(getStorableRequestParams(params_1));
|
|
248
251
|
prevStringyParams = this.storage.get('lastStringyParams');
|
|
249
252
|
if (stringyParams == prevStringyParams) {
|
|
250
253
|
// no param change - not searching
|
|
@@ -263,6 +266,7 @@ var SearchController = /** @class */ (function (_super) {
|
|
|
263
266
|
return [2 /*return*/];
|
|
264
267
|
}
|
|
265
268
|
if (!(((_l = this.config.settings) === null || _l === void 0 ? void 0 : _l.infinite.backfill) && !this.store.loaded)) return [3 /*break*/, 8];
|
|
269
|
+
backfillRequestsParams_1 = [];
|
|
266
270
|
backfillRequests = Array(params_1.pagination.page)
|
|
267
271
|
.fill('backfill')
|
|
268
272
|
.map(function (v, i) {
|
|
@@ -277,6 +281,7 @@ var SearchController = /** @class */ (function (_super) {
|
|
|
277
281
|
(_d = backfillParams === null || backfillParams === void 0 ? void 0 : backfillParams.search) === null || _d === void 0 ? true : delete _d.redirectResponse;
|
|
278
282
|
}
|
|
279
283
|
}
|
|
284
|
+
backfillRequestsParams_1.push(backfillParams);
|
|
280
285
|
return _this.client.search(backfillParams);
|
|
281
286
|
});
|
|
282
287
|
return [4 /*yield*/, Promise.all(backfillRequests)];
|
|
@@ -286,8 +291,8 @@ var SearchController = /** @class */ (function (_super) {
|
|
|
286
291
|
// set the meta and response to the first page of backfillResponses
|
|
287
292
|
meta = backfillResponses[0][0];
|
|
288
293
|
response = backfillResponses[0][1];
|
|
289
|
-
backfillResults = backfillResponses.reduce(function (results, response) {
|
|
290
|
-
|
|
294
|
+
backfillResults = backfillResponses.reduce(function (results, response, index) {
|
|
295
|
+
createResultSchemaMapping({ request: backfillRequestsParams_1[index], response: response });
|
|
291
296
|
return results.concat.apply(results, response[1].results);
|
|
292
297
|
}, []);
|
|
293
298
|
// overwrite pagination params to expected state
|
|
@@ -300,6 +305,7 @@ var SearchController = /** @class */ (function (_super) {
|
|
|
300
305
|
case 9:
|
|
301
306
|
// infinite with no backfills.
|
|
302
307
|
_a = _o.sent(), meta = _a[0], response = _a[1];
|
|
308
|
+
createResultSchemaMapping({ request: params_1, response: [meta, response] });
|
|
303
309
|
// append new results to previous results
|
|
304
310
|
response.results = __spreadArray(__spreadArray([], this.previousResults, true), (response.results || []), true);
|
|
305
311
|
_o.label = 10;
|
|
@@ -313,6 +319,7 @@ var SearchController = /** @class */ (function (_super) {
|
|
|
313
319
|
return [4 /*yield*/, this.client.search(params_1)];
|
|
314
320
|
case 12:
|
|
315
321
|
_b = _o.sent(), meta = _b[0], response = _b[1];
|
|
322
|
+
createResultSchemaMapping({ request: params_1, response: [meta, response] });
|
|
316
323
|
_o.label = 13;
|
|
317
324
|
case 13:
|
|
318
325
|
// MockClient will overwrite the client search() method and use SearchData to return mock data which already contains meta data
|
|
@@ -429,10 +436,17 @@ var SearchController = /** @class */ (function (_super) {
|
|
|
429
436
|
}
|
|
430
437
|
});
|
|
431
438
|
}); };
|
|
432
|
-
_this.addToCart = function (
|
|
439
|
+
_this.addToCart = function (_products) { return __awaiter(_this, void 0, void 0, function () {
|
|
440
|
+
var products;
|
|
441
|
+
var _this = this;
|
|
433
442
|
return __generator(this, function (_a) {
|
|
434
|
-
|
|
435
|
-
|
|
443
|
+
products = typeof _products.slice == 'function' ? _products.slice() : [_products];
|
|
444
|
+
products.forEach(function (product) {
|
|
445
|
+
_this.track.product.addToCart(product);
|
|
446
|
+
});
|
|
447
|
+
if (products.length > 0) {
|
|
448
|
+
this.eventManager.fire('addToCart', { controller: this, products: products });
|
|
449
|
+
}
|
|
436
450
|
return [2 /*return*/];
|
|
437
451
|
});
|
|
438
452
|
}); };
|
|
@@ -498,10 +512,10 @@ var SearchController = /** @class */ (function (_super) {
|
|
|
498
512
|
});
|
|
499
513
|
// add 'afterSearch' middleware
|
|
500
514
|
_this.eventManager.on('afterSearch', function (search, next) { return __awaiter(_this, void 0, void 0, function () {
|
|
501
|
-
var config, redirectURL, searchStore
|
|
502
|
-
var _a, _b, _c, _d, _e, _f
|
|
503
|
-
return __generator(this, function (
|
|
504
|
-
switch (
|
|
515
|
+
var config, redirectURL, searchStore;
|
|
516
|
+
var _a, _b, _c, _d, _e, _f;
|
|
517
|
+
return __generator(this, function (_g) {
|
|
518
|
+
switch (_g.label) {
|
|
505
519
|
case 0:
|
|
506
520
|
config = search.controller.config;
|
|
507
521
|
redirectURL = (_b = (_a = search.response) === null || _a === void 0 ? void 0 : _a.merchandising) === null || _b === void 0 ? void 0 : _b.redirect;
|
|
@@ -513,19 +527,9 @@ var SearchController = /** @class */ (function (_super) {
|
|
|
513
527
|
window.location.replace(redirectURL);
|
|
514
528
|
return [2 /*return*/, false];
|
|
515
529
|
}
|
|
516
|
-
nonBackgroundFilters = (_h = (_g = search === null || search === void 0 ? void 0 : search.request) === null || _g === void 0 ? void 0 : _g.filters) === null || _h === void 0 ? void 0 : _h.filter(function (filter) { return !filter.background; });
|
|
517
|
-
if (((_k = (_j = config === null || config === void 0 ? void 0 : config.settings) === null || _j === void 0 ? void 0 : _j.redirects) === null || _k === void 0 ? void 0 : _k.singleResult) &&
|
|
518
|
-
((_m = (_l = search === null || search === void 0 ? void 0 : search.response) === null || _l === void 0 ? void 0 : _l.search) === null || _m === void 0 ? void 0 : _m.query) &&
|
|
519
|
-
((_p = (_o = search === null || search === void 0 ? void 0 : search.response) === null || _o === void 0 ? void 0 : _o.pagination) === null || _p === void 0 ? void 0 : _p.totalResults) === 1 &&
|
|
520
|
-
!(nonBackgroundFilters === null || nonBackgroundFilters === void 0 ? void 0 : nonBackgroundFilters.length)) {
|
|
521
|
-
//set loaded to true to prevent infinite search/reloading from happening
|
|
522
|
-
searchStore.loaded = true;
|
|
523
|
-
window.location.replace(search === null || search === void 0 ? void 0 : search.response.results[0].mappings.core.url);
|
|
524
|
-
return [2 /*return*/, false];
|
|
525
|
-
}
|
|
526
530
|
return [4 /*yield*/, next()];
|
|
527
531
|
case 1:
|
|
528
|
-
|
|
532
|
+
_g.sent();
|
|
529
533
|
return [2 /*return*/];
|
|
530
534
|
}
|
|
531
535
|
});
|
|
@@ -537,10 +541,9 @@ var SearchController = /** @class */ (function (_super) {
|
|
|
537
541
|
case 0: return [4 /*yield*/, next()];
|
|
538
542
|
case 1:
|
|
539
543
|
_a.sent();
|
|
540
|
-
// save last params
|
|
541
|
-
this.storage.set('lastStringyParams', JSON.stringify(search.request));
|
|
542
544
|
storableRequestParams = getStorableRequestParams(search.request);
|
|
543
545
|
stringyParams = JSON.stringify(storableRequestParams);
|
|
546
|
+
this.storage.set('lastStringyParams', stringyParams);
|
|
544
547
|
scrollMap = this.storage.get('scrollMap') || {};
|
|
545
548
|
elementPosition = scrollMap[stringyParams];
|
|
546
549
|
if (!elementPosition) {
|
|
@@ -553,6 +556,44 @@ var SearchController = /** @class */ (function (_super) {
|
|
|
553
556
|
}
|
|
554
557
|
});
|
|
555
558
|
}); });
|
|
559
|
+
_this.eventManager.on('afterStore', function (search, next) { return __awaiter(_this, void 0, void 0, function () {
|
|
560
|
+
var controller, products, data, config_1, nonBackgroundFilters;
|
|
561
|
+
var _this = this;
|
|
562
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
563
|
+
return __generator(this, function (_k) {
|
|
564
|
+
switch (_k.label) {
|
|
565
|
+
case 0: return [4 /*yield*/, next()];
|
|
566
|
+
case 1:
|
|
567
|
+
_k.sent();
|
|
568
|
+
controller = search.controller;
|
|
569
|
+
if (controller.store.loaded && !controller.store.error) {
|
|
570
|
+
products = controller.store.results.filter(function (result) { var _a; return result.type === 'product' && !((_a = _this.events.product[result.id]) === null || _a === void 0 ? void 0 : _a.render); });
|
|
571
|
+
if (products.length === 0) {
|
|
572
|
+
data = getSearchSchemaData({ params: search.request, results: [] });
|
|
573
|
+
this.tracker.events[this.pageType].render({ data: data, siteId: (_a = this.config.globals) === null || _a === void 0 ? void 0 : _a.siteId });
|
|
574
|
+
}
|
|
575
|
+
products.forEach(function (result) {
|
|
576
|
+
var _a;
|
|
577
|
+
var data = schemaMap[result.id];
|
|
578
|
+
_this.tracker.events[_this.pageType].render({ data: data, siteId: (_a = _this.config.globals) === null || _a === void 0 ? void 0 : _a.siteId });
|
|
579
|
+
_this.events.product[result.id] = _this.events.product[result.id] || {};
|
|
580
|
+
_this.events.product[result.id].render = true;
|
|
581
|
+
_this.eventManager.fire('track.product.render', { controller: _this, product: result, trackEvent: data });
|
|
582
|
+
});
|
|
583
|
+
config_1 = search.controller.config;
|
|
584
|
+
nonBackgroundFilters = (_c = (_b = search === null || search === void 0 ? void 0 : search.request) === null || _b === void 0 ? void 0 : _b.filters) === null || _c === void 0 ? void 0 : _c.filter(function (filter) { return !filter.background; });
|
|
585
|
+
if (((_e = (_d = config_1 === null || config_1 === void 0 ? void 0 : config_1.settings) === null || _d === void 0 ? void 0 : _d.redirects) === null || _e === void 0 ? void 0 : _e.singleResult) &&
|
|
586
|
+
((_g = (_f = search === null || search === void 0 ? void 0 : search.response) === null || _f === void 0 ? void 0 : _f.search) === null || _g === void 0 ? void 0 : _g.query) &&
|
|
587
|
+
((_j = (_h = search === null || search === void 0 ? void 0 : search.response) === null || _h === void 0 ? void 0 : _h.pagination) === null || _j === void 0 ? void 0 : _j.totalResults) === 1 &&
|
|
588
|
+
!(nonBackgroundFilters === null || nonBackgroundFilters === void 0 ? void 0 : nonBackgroundFilters.length)) {
|
|
589
|
+
window.location.replace(search === null || search === void 0 ? void 0 : search.response.results[0].mappings.core.url);
|
|
590
|
+
return [2 /*return*/, false];
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
return [2 /*return*/];
|
|
594
|
+
}
|
|
595
|
+
});
|
|
596
|
+
}); });
|
|
556
597
|
// restore position
|
|
557
598
|
if ((_d = (_c = _this.config.settings) === null || _c === void 0 ? void 0 : _c.restorePosition) === null || _d === void 0 ? void 0 : _d.enabled) {
|
|
558
599
|
_this.eventManager.on('restorePosition', function (_a, next) {
|
|
@@ -703,6 +744,26 @@ var SearchController = /** @class */ (function (_super) {
|
|
|
703
744
|
return SearchController;
|
|
704
745
|
}(AbstractController_1.AbstractController));
|
|
705
746
|
exports.SearchController = SearchController;
|
|
747
|
+
function createResultSchemaMapping(_a) {
|
|
748
|
+
var _b;
|
|
749
|
+
var request = _a.request, response = _a.response;
|
|
750
|
+
var _ = response[0], searchResponse = response[1];
|
|
751
|
+
var schema = getSearchSchemaData({
|
|
752
|
+
params: request,
|
|
753
|
+
results: [], // results added below because this would contain all results
|
|
754
|
+
response: searchResponse,
|
|
755
|
+
});
|
|
756
|
+
(_b = searchResponse.results) === null || _b === void 0 ? void 0 : _b.forEach(function (result) {
|
|
757
|
+
var _a, _b, _c, _d;
|
|
758
|
+
schemaMap[result.id] = __assign(__assign({}, schema), { results: [
|
|
759
|
+
{
|
|
760
|
+
position: result.position,
|
|
761
|
+
uid: ((_b = (_a = result.mappings) === null || _a === void 0 ? void 0 : _a.core) === null || _b === void 0 ? void 0 : _b.uid) || '',
|
|
762
|
+
sku: (_d = (_c = result.mappings) === null || _c === void 0 ? void 0 : _c.core) === null || _d === void 0 ? void 0 : _d.sku,
|
|
763
|
+
},
|
|
764
|
+
] });
|
|
765
|
+
});
|
|
766
|
+
}
|
|
706
767
|
function getStorableRequestParams(request) {
|
|
707
768
|
var _a, _b, _c, _d;
|
|
708
769
|
return {
|
|
@@ -755,9 +816,21 @@ function getSearchRedirectSchemaData(_a) {
|
|
|
755
816
|
redirect: redirectURL,
|
|
756
817
|
};
|
|
757
818
|
}
|
|
819
|
+
function getSearchAddtocartSchemaData(_a) {
|
|
820
|
+
var searchSchemaData = _a.searchSchemaData, results = _a.results;
|
|
821
|
+
return __assign(__assign({}, searchSchemaData), { results: (results === null || results === void 0 ? void 0 : results.map(function (result) {
|
|
822
|
+
var core = result.mappings.core;
|
|
823
|
+
return {
|
|
824
|
+
uid: core.uid || '',
|
|
825
|
+
sku: core.sku,
|
|
826
|
+
price: Number(core.price),
|
|
827
|
+
qty: result.quantity || 1,
|
|
828
|
+
};
|
|
829
|
+
})) || [] });
|
|
830
|
+
}
|
|
758
831
|
function getSearchSchemaData(_a) {
|
|
759
|
-
var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
760
|
-
var params = _a.params,
|
|
832
|
+
var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
|
|
833
|
+
var params = _a.params, results = _a.results, response = _a.response;
|
|
761
834
|
var filters = (_b = params.filters) === null || _b === void 0 ? void 0 : _b.reduce(function (acc, filter) {
|
|
762
835
|
var _a;
|
|
763
836
|
var _b, _c, _d, _e;
|
|
@@ -780,35 +853,42 @@ function getSearchSchemaData(_a) {
|
|
|
780
853
|
}
|
|
781
854
|
return acc;
|
|
782
855
|
}, {});
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
856
|
+
var correctedQuery;
|
|
857
|
+
if (((_c = response === null || response === void 0 ? void 0 : response.search) === null || _c === void 0 ? void 0 : _c.originalQuery) && ((_d = response === null || response === void 0 ? void 0 : response.search) === null || _d === void 0 ? void 0 : _d.query)) {
|
|
858
|
+
correctedQuery = (_e = response === null || response === void 0 ? void 0 : response.search) === null || _e === void 0 ? void 0 : _e.query;
|
|
859
|
+
}
|
|
860
|
+
var campaigns = ((_f = response === null || response === void 0 ? void 0 : response.merchandising) === null || _f === void 0 ? void 0 : _f.campaigns) || [];
|
|
861
|
+
var experiments = ((_g = response === null || response === void 0 ? void 0 : response.merchandising) === null || _g === void 0 ? void 0 : _g.experiments) || [];
|
|
862
|
+
return __assign(__assign({ q: ((_j = (_h = params.search) === null || _h === void 0 ? void 0 : _h.query) === null || _j === void 0 ? void 0 : _j.string) || '', correctedQuery: correctedQuery, matchType: (_k = response === null || response === void 0 ? void 0 : response.search) === null || _k === void 0 ? void 0 : _k.matchType }, filters), { sort: (_l = params.sorts) === null || _l === void 0 ? void 0 : _l.map(function (sort) {
|
|
863
|
+
return {
|
|
864
|
+
field: sort.field,
|
|
865
|
+
dir: sort.direction,
|
|
866
|
+
};
|
|
867
|
+
}), pagination: {
|
|
868
|
+
totalResults: (_m = response === null || response === void 0 ? void 0 : response.pagination) === null || _m === void 0 ? void 0 : _m.totalResults,
|
|
869
|
+
page: (_o = response === null || response === void 0 ? void 0 : response.pagination) === null || _o === void 0 ? void 0 : _o.page,
|
|
870
|
+
resultsPerPage: (_p = response === null || response === void 0 ? void 0 : response.pagination) === null || _p === void 0 ? void 0 : _p.pageSize,
|
|
792
871
|
}, merchandising: {
|
|
793
|
-
personalized:
|
|
794
|
-
redirect:
|
|
795
|
-
triggeredCampaigns: (
|
|
796
|
-
|
|
797
|
-
var experiement =
|
|
872
|
+
personalized: (_q = response === null || response === void 0 ? void 0 : response.merchandising) === null || _q === void 0 ? void 0 : _q.personalized,
|
|
873
|
+
redirect: (_r = response === null || response === void 0 ? void 0 : response.merchandising) === null || _r === void 0 ? void 0 : _r.redirect,
|
|
874
|
+
triggeredCampaigns: (campaigns.length &&
|
|
875
|
+
campaigns.map(function (campaign) {
|
|
876
|
+
var experiement = experiments.find(function (experiment) { return experiment.campaignId === campaign.id; });
|
|
798
877
|
return {
|
|
799
878
|
id: campaign.id,
|
|
800
879
|
experimentId: experiement === null || experiement === void 0 ? void 0 : experiement.experimentId,
|
|
801
880
|
variationId: experiement === null || experiement === void 0 ? void 0 : experiement.variationId,
|
|
802
881
|
};
|
|
803
|
-
}))
|
|
882
|
+
})) ||
|
|
804
883
|
undefined,
|
|
805
884
|
}, results: (results === null || results === void 0 ? void 0 : results.map(function (result) {
|
|
806
|
-
var
|
|
885
|
+
var _a;
|
|
886
|
+
var core = (_a = result.mappings) === null || _a === void 0 ? void 0 : _a.core;
|
|
887
|
+
var position = result.position;
|
|
807
888
|
return {
|
|
889
|
+
position: position,
|
|
808
890
|
uid: core.uid || '',
|
|
809
|
-
// childUid: core.uid,
|
|
810
891
|
sku: core.sku,
|
|
811
|
-
// childSku: core.sku,
|
|
812
892
|
};
|
|
813
893
|
})) || [] });
|
|
814
894
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Product } from '@searchspring/snap-store-mobx';
|
|
2
|
+
export declare const CLICK_DUPLICATION_TIMEOUT = 300;
|
|
3
|
+
export declare const CLICK_THROUGH_CLOSEST_MAX_LEVELS = 12;
|
|
4
|
+
export declare const isClickWithinProductLink: (e: MouseEvent, result: Product) => boolean;
|
|
5
|
+
//# sourceMappingURL=isClickWithinProductLink.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"isClickWithinProductLink.d.ts","sourceRoot":"","sources":["../../../src/utils/isClickWithinProductLink.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AAE7D,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAC7C,eAAO,MAAM,gCAAgC,KAAK,CAAC;AAEnD,eAAO,MAAM,wBAAwB,MAAO,UAAU,UAAU,OAAO,KAAG,OAezE,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isClickWithinProductLink = exports.CLICK_THROUGH_CLOSEST_MAX_LEVELS = exports.CLICK_DUPLICATION_TIMEOUT = void 0;
|
|
4
|
+
exports.CLICK_DUPLICATION_TIMEOUT = 300;
|
|
5
|
+
exports.CLICK_THROUGH_CLOSEST_MAX_LEVELS = 12;
|
|
6
|
+
var isClickWithinProductLink = function (e, result) {
|
|
7
|
+
var _a, _b, _c;
|
|
8
|
+
var currentElement = e.target;
|
|
9
|
+
var href = null;
|
|
10
|
+
var level = 0;
|
|
11
|
+
var resultUrl = ((_b = (_a = result === null || result === void 0 ? void 0 : result.display) === null || _a === void 0 ? void 0 : _a.mappings.core) === null || _b === void 0 ? void 0 : _b.url) || ((_c = result === null || result === void 0 ? void 0 : result.mappings.core) === null || _c === void 0 ? void 0 : _c.url) || '';
|
|
12
|
+
while (currentElement && level < exports.CLICK_THROUGH_CLOSEST_MAX_LEVELS) {
|
|
13
|
+
href = currentElement.getAttribute('href');
|
|
14
|
+
if (href && resultUrl && href.includes(resultUrl)) {
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
currentElement = currentElement.parentElement;
|
|
18
|
+
level++;
|
|
19
|
+
}
|
|
20
|
+
return false;
|
|
21
|
+
};
|
|
22
|
+
exports.isClickWithinProductLink = isClickWithinProductLink;
|
|
@@ -23,6 +23,7 @@ export declare class AutocompleteController extends AbstractController {
|
|
|
23
23
|
storage: StorageStore;
|
|
24
24
|
events: {
|
|
25
25
|
product: Record<string, {
|
|
26
|
+
click?: boolean;
|
|
26
27
|
clickThrough?: boolean;
|
|
27
28
|
impression?: boolean;
|
|
28
29
|
render?: boolean;
|
|
@@ -51,7 +52,7 @@ export declare class AutocompleteController extends AbstractController {
|
|
|
51
52
|
bind(): Promise<void>;
|
|
52
53
|
searchTrending: () => Promise<void>;
|
|
53
54
|
search: () => Promise<void>;
|
|
54
|
-
addToCart: (
|
|
55
|
+
addToCart: (_products: Product[] | Product) => Promise<void>;
|
|
55
56
|
}
|
|
56
57
|
export {};
|
|
57
58
|
//# sourceMappingURL=AutocompleteController.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AutocompleteController.d.ts","sourceRoot":"","sources":["../../../src/Autocomplete/AutocompleteController.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,YAAY,EAAa,OAAO,
|
|
1
|
+
{"version":3,"file":"AutocompleteController.d.ts","sourceRoot":"","sources":["../../../src/Autocomplete/AutocompleteController.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,YAAY,EAAa,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AACzF,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAEpE,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,KAAK,EAAE,4BAA4B,EAAiC,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAElI,OAAO,KAAK,EAAE,wBAAwB,EAAgE,MAAM,2BAA2B,CAAC;AAcxI,eAAO,MAAM,WAAW,MAAM,CAAC;AA+B/B,KAAK,wBAAwB,GAAG;IAC/B,OAAO,EAAE;QACR,YAAY,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;QACvD,KAAK,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,KAAK,IAAI,CAAC;QACzD,MAAM,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;QAClC,UAAU,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;QACtC,SAAS,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;KACtC,CAAC;IACF,QAAQ,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC,CAAC;AAEF,qBAAa,sBAAuB,SAAQ,kBAAkB;IACtD,IAAI,kBAAgC;IACnC,KAAK,EAAE,iBAAiB,CAAC;IACzB,MAAM,EAAE,4BAA4B,CAAC;IACtC,OAAO,EAAE,YAAY,CAAC;IAE7B,MAAM,EAAE;QACP,OAAO,EAAE,MAAM,CACd,MAAM,EACN;YACC,KAAK,CAAC,EAAE,OAAO,CAAC;YAChB,YAAY,CAAC,EAAE,OAAO,CAAC;YACvB,UAAU,CAAC,EAAE,OAAO,CAAC;YACrB,MAAM,CAAC,EAAE,OAAO,CAAC;SACjB,CACD,CAAC;KACF,CAEC;gBAGD,MAAM,EAAE,4BAA4B,EACpC,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,kBAAkB,EAC1F,OAAO,CAAC,EAAE,gBAAgB;IA4E3B,KAAK,EAAE,wBAAwB,CA0D7B;IAEF,IAAI,MAAM,IAAI,wBAAwB,CAwCrC;IAEK,UAAU,CAAC,YAAY,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IA2BhE,KAAK,IAAI,IAAI;IASb,QAAQ;;0BAEc,aAAa,KAAG,QAAQ,OAAO,GAAG,SAAS,CAAC;wBAkDpD,aAAa,KAAG,IAAI;uBAMrB,UAAU,KAAG,IAAI;4BAQN,MAAM,SAAS,CAAC,gBAAgB,CAAC,KAAG,QAAQ,IAAI,CAAC;mCAgDhD,MAAM,WAAW,CAAC,gBAAgB,CAAC,KAAG,IAAI;uBAqBtD,KAAK;;;;uBAyDL,UAAU,KAAG,IAAI;;MAS5B;IAEF,MAAM,IAAI,IAAI;IAgBR,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAgF3B,cAAc,QAAa,QAAQ,IAAI,CAAC,CAwBtC;IAEF,MAAM,QAAa,QAAQ,IAAI,CAAC,CA0I9B;IAEF,SAAS,cAAqB,OAAO,EAAE,GAAG,OAAO,KAAG,QAAQ,IAAI,CAAC,CAQ/D;CACF"}
|
|
@@ -3,6 +3,7 @@ import { StorageStore, ErrorType } from '@searchspring/snap-store-mobx';
|
|
|
3
3
|
import { AbstractController } from '../Abstract/AbstractController';
|
|
4
4
|
import { getSearchParams } from '../utils/getParams';
|
|
5
5
|
import { ControllerTypes } from '../types';
|
|
6
|
+
import { CLICK_DUPLICATION_TIMEOUT, isClickWithinProductLink } from '../utils/isClickWithinProductLink';
|
|
6
7
|
const INPUT_ATTRIBUTE = 'ss-autocomplete-input';
|
|
7
8
|
export const INPUT_DELAY = 200;
|
|
8
9
|
const KEY_ENTER = 13;
|
|
@@ -50,29 +51,30 @@ export class AutocompleteController extends AbstractController {
|
|
|
50
51
|
this.tracker.events.autocomplete.clickThrough({ data, siteId: this.config.globals?.siteId });
|
|
51
52
|
this.events.product[result.id] = this.events.product[result.id] || {};
|
|
52
53
|
this.events.product[result.id].clickThrough = true;
|
|
53
|
-
this.eventManager.fire('track.product.clickThrough', { controller: this, event: e,
|
|
54
|
+
this.eventManager.fire('track.product.clickThrough', { controller: this, event: e, product: result, trackEvent: data });
|
|
54
55
|
},
|
|
55
56
|
click: (e, result) => {
|
|
56
|
-
if (result.
|
|
57
|
+
if (this.events.product[result.id]?.click) {
|
|
57
58
|
return;
|
|
58
59
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
if (href) {
|
|
62
|
-
this.track.product.clickThrough(e, result);
|
|
63
|
-
}
|
|
64
|
-
else {
|
|
65
|
-
// TODO: in future, send as an interaction event
|
|
60
|
+
if (result.type === 'banner') {
|
|
61
|
+
return;
|
|
66
62
|
}
|
|
63
|
+
isClickWithinProductLink(e, result) && this.track.product.clickThrough(e, result);
|
|
64
|
+
this.events.product[result.id] = this.events.product[result.id] || {};
|
|
65
|
+
this.events.product[result.id].click = true;
|
|
66
|
+
setTimeout(() => {
|
|
67
|
+
this.events.product[result.id].click = false;
|
|
68
|
+
}, CLICK_DUPLICATION_TIMEOUT);
|
|
67
69
|
},
|
|
68
70
|
render: (result) => {
|
|
69
71
|
if (this.events.product[result.id]?.render)
|
|
70
72
|
return;
|
|
71
|
-
const data = getAutocompleteSchemaData({ params: this.params, store: this.store, results: [result] });
|
|
73
|
+
const data = getAutocompleteSchemaData({ params: this.params, store: this.store, results: result ? [result] : [] });
|
|
72
74
|
this.tracker.events.autocomplete.render({ data, siteId: this.config.globals?.siteId });
|
|
73
75
|
this.events.product[result.id] = this.events.product[result.id] || {};
|
|
74
76
|
this.events.product[result.id].render = true;
|
|
75
|
-
this.eventManager.fire('track.product.render', { controller: this,
|
|
77
|
+
this.eventManager.fire('track.product.render', { controller: this, product: result, trackEvent: data });
|
|
76
78
|
},
|
|
77
79
|
impression: (result) => {
|
|
78
80
|
if (this.events.product[result.id]?.impression)
|
|
@@ -81,18 +83,18 @@ export class AutocompleteController extends AbstractController {
|
|
|
81
83
|
this.tracker.events.autocomplete.impression({ data, siteId: this.config.globals?.siteId });
|
|
82
84
|
this.events.product[result.id] = this.events.product[result.id] || {};
|
|
83
85
|
this.events.product[result.id].impression = true;
|
|
84
|
-
this.eventManager.fire('track.product.impression', { controller: this,
|
|
86
|
+
this.eventManager.fire('track.product.impression', { controller: this, product: result, trackEvent: data });
|
|
85
87
|
},
|
|
86
88
|
addToCart: (result) => {
|
|
87
|
-
const data =
|
|
89
|
+
const data = getAutocompleteAddtocartSchemaData({ params: this.params, store: this.store, results: [result] });
|
|
88
90
|
this.tracker.events.autocomplete.addToCart({ data, siteId: this.config.globals?.siteId });
|
|
89
|
-
this.eventManager.fire('track.product.addToCart', { controller: this,
|
|
91
|
+
this.eventManager.fire('track.product.addToCart', { controller: this, product: result, trackEvent: data });
|
|
90
92
|
},
|
|
91
93
|
},
|
|
92
94
|
redirect: (redirectURL) => {
|
|
93
95
|
const data = getAutocompleteRedirectSchemaData({ redirectURL });
|
|
94
96
|
this.tracker.events.autocomplete.redirect({ data, siteId: this.config.globals?.siteId });
|
|
95
|
-
this.eventManager.fire('track.
|
|
97
|
+
this.eventManager.fire('track.redirect', { controller: this, redirectURL, trackEvent: data });
|
|
96
98
|
},
|
|
97
99
|
};
|
|
98
100
|
this.handlers = {
|
|
@@ -307,8 +309,6 @@ export class AutocompleteController extends AbstractController {
|
|
|
307
309
|
if (!this.initialized) {
|
|
308
310
|
await this.init();
|
|
309
311
|
}
|
|
310
|
-
// reset events for new search
|
|
311
|
-
this.events = { product: {} };
|
|
312
312
|
// if urlManager has no query, there will be no need to get params and no query
|
|
313
313
|
if (!this.urlManager.state.query) {
|
|
314
314
|
return;
|
|
@@ -434,9 +434,14 @@ export class AutocompleteController extends AbstractController {
|
|
|
434
434
|
this.store.loading = false;
|
|
435
435
|
}
|
|
436
436
|
};
|
|
437
|
-
this.addToCart = async (
|
|
438
|
-
|
|
439
|
-
|
|
437
|
+
this.addToCart = async (_products) => {
|
|
438
|
+
const products = typeof _products.slice == 'function' ? _products.slice() : [_products];
|
|
439
|
+
products.forEach((product) => {
|
|
440
|
+
this.track.product.addToCart(product);
|
|
441
|
+
});
|
|
442
|
+
if (products.length > 0) {
|
|
443
|
+
this.eventManager.fire('addToCart', { controller: this, products });
|
|
444
|
+
}
|
|
440
445
|
};
|
|
441
446
|
// deep merge config with defaults
|
|
442
447
|
this.config = deepmerge(defaultConfig, this.config);
|
|
@@ -453,6 +458,23 @@ export class AutocompleteController extends AbstractController {
|
|
|
453
458
|
type: 'session',
|
|
454
459
|
key: `ss-controller-${this.config.id}`,
|
|
455
460
|
});
|
|
461
|
+
this.eventManager.on('afterStore', async (search, next) => {
|
|
462
|
+
await next();
|
|
463
|
+
const controller = search.controller;
|
|
464
|
+
if (controller.store.loaded && !controller.store.error) {
|
|
465
|
+
const products = controller.store.results.filter((result) => result.type === 'product');
|
|
466
|
+
const results = products.length === 0 ? [] : products;
|
|
467
|
+
const data = getAutocompleteSchemaData({ params: search.request, store: this.store, results });
|
|
468
|
+
this.tracker.events.autocomplete.render({ data, siteId: this.config.globals?.siteId });
|
|
469
|
+
products.forEach((result) => {
|
|
470
|
+
this.events.product[result.id] = this.events.product[result.id] || {};
|
|
471
|
+
this.events.product[result.id].render = true;
|
|
472
|
+
this.eventManager.fire('track.product.render', { controller: this, product: result, trackEvent: data });
|
|
473
|
+
});
|
|
474
|
+
// reset events for new search. It's here for a reason. Ensures render happens before impressions on new input value?
|
|
475
|
+
this.events = { product: {} };
|
|
476
|
+
}
|
|
477
|
+
});
|
|
456
478
|
// add 'afterSearch' middleware
|
|
457
479
|
this.eventManager.on('afterSearch', async (ac, next) => {
|
|
458
480
|
await next();
|
|
@@ -692,6 +714,21 @@ function getAutocompleteRedirectSchemaData({ redirectURL }) {
|
|
|
692
714
|
redirect: redirectURL,
|
|
693
715
|
};
|
|
694
716
|
}
|
|
717
|
+
function getAutocompleteAddtocartSchemaData({ params, store, results, }) {
|
|
718
|
+
const base = getAutocompleteSchemaData({ params, store, results });
|
|
719
|
+
return {
|
|
720
|
+
...base,
|
|
721
|
+
results: results?.map((result) => {
|
|
722
|
+
const core = result.mappings.core;
|
|
723
|
+
return {
|
|
724
|
+
uid: core.uid || '',
|
|
725
|
+
sku: core.sku,
|
|
726
|
+
price: Number(core.price),
|
|
727
|
+
qty: result.quantity || 1,
|
|
728
|
+
};
|
|
729
|
+
}) || [],
|
|
730
|
+
};
|
|
731
|
+
}
|
|
695
732
|
function getAutocompleteSchemaData({ params, store, results, }) {
|
|
696
733
|
const filters = params.filters?.reduce((acc, filter) => {
|
|
697
734
|
const key = filter.background ? 'bgfilter' : 'filter';
|
|
@@ -716,13 +753,14 @@ function getAutocompleteSchemaData({ params, store, results, }) {
|
|
|
716
753
|
return {
|
|
717
754
|
q: store.search?.originalQuery?.string || store.search?.query?.string || '',
|
|
718
755
|
correctedQuery: store.search?.originalQuery?.string ? store.search?.query?.string : undefined,
|
|
756
|
+
matchType: store.search.matchType,
|
|
719
757
|
...filters,
|
|
720
|
-
sort:
|
|
721
|
-
{
|
|
722
|
-
field:
|
|
723
|
-
dir:
|
|
724
|
-
}
|
|
725
|
-
|
|
758
|
+
sort: params.sorts?.map((sort) => {
|
|
759
|
+
return {
|
|
760
|
+
field: sort.field,
|
|
761
|
+
dir: sort.direction,
|
|
762
|
+
};
|
|
763
|
+
}),
|
|
726
764
|
pagination: {
|
|
727
765
|
totalResults: store.pagination.totalResults,
|
|
728
766
|
page: store.pagination.page,
|
|
@@ -744,11 +782,11 @@ function getAutocompleteSchemaData({ params, store, results, }) {
|
|
|
744
782
|
},
|
|
745
783
|
results: results?.map((result) => {
|
|
746
784
|
const core = result.mappings.core;
|
|
785
|
+
const position = result.position;
|
|
747
786
|
return {
|
|
787
|
+
position,
|
|
748
788
|
uid: core.uid || '',
|
|
749
|
-
// childUid: core.uid,
|
|
750
789
|
sku: core.sku,
|
|
751
|
-
// childSku: core.sku,
|
|
752
790
|
};
|
|
753
791
|
}) || [],
|
|
754
792
|
};
|