coveo-search-ui
Version:
Coveo JavaScript Search Framework
463 lines (449 loc) • 22 kB
JavaScript
webpackJsonpCoveo__temporary([43],{
/***/ 201:
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
__webpack_require__(662);
var underscore_1 = __webpack_require__(0);
var InitializationEvents_1 = __webpack_require__(17);
var QueryEvents_1 = __webpack_require__(11);
var ResultLayoutEvents_1 = __webpack_require__(134);
var ResultListEvents_1 = __webpack_require__(29);
var Assert_1 = __webpack_require__(5);
var Model_1 = __webpack_require__(18);
var QueryStateModel_1 = __webpack_require__(13);
var GlobalExports_1 = __webpack_require__(3);
var Strings_1 = __webpack_require__(6);
var Dom_1 = __webpack_require__(1);
var SVGDom_1 = __webpack_require__(16);
var SVGIcons_1 = __webpack_require__(12);
var Utils_1 = __webpack_require__(4);
var AnalyticsActionListMeta_1 = __webpack_require__(10);
var Component_1 = __webpack_require__(7);
var ComponentOptions_1 = __webpack_require__(8);
var Initialization_1 = __webpack_require__(2);
var ResponsiveResultLayout_1 = __webpack_require__(663);
var AccessibleButton_1 = __webpack_require__(15);
exports.defaultLayout = 'list';
/**
* The ResultLayoutSelector component allows the end user to switch between multiple {@link ResultList} components that have
* different {@link ResultList.options.layout} values.
*
* This component automatically populates itself with buttons to switch between the ResultList components that have a
* valid layout value (see the {@link ValidLayout} type).
*
* See also the [Result Layouts](https://docs.coveo.com/en/360/) documentation.
*
* @availablesince [February 2018 Release (v2.3826.10)](https://docs.coveo.com/en/410/#february-2018-release-v2382610)
*/
var ResultLayoutSelector = /** @class */ (function (_super) {
__extends(ResultLayoutSelector, _super);
/**
* Creates a new ResultLayoutSelector component.
* @param element The HTMLElement on which to instantiate the component.
* @param options The options for the ResultLayout component.
* @param bindings The bindings that the component requires to function normally. If not set, these will be
* automatically resolved (with a slower execution time).
*/
function ResultLayoutSelector(element, options, bindings) {
var _this = _super.call(this, element, ResultLayoutSelector.ID, bindings) || this;
_this.element = element;
_this.options = options;
_this.preferredLayout = null;
_this.options = ComponentOptions_1.ComponentOptions.initComponentOptions(element, ResultLayoutSelector, options);
_this.currentActiveLayouts = {};
_this.bind.onQueryState(Model_1.MODEL_EVENTS.CHANGE_ONE, QueryStateModel_1.QUERY_STATE_ATTRIBUTES.LAYOUT, _this.handleQueryStateChanged.bind(_this));
_this.bind.onRootElement(QueryEvents_1.QueryEvents.querySuccess, function (args) { return _this.handleQuerySuccess(args); });
_this.bind.onRootElement(QueryEvents_1.QueryEvents.queryError, function (args) { return _this.handleQueryError(args); });
_this.resultLayoutSection = Dom_1.$$(_this.element).closest('.coveo-result-layout-section');
_this.bind.oneRootElement(InitializationEvents_1.InitializationEvents.afterComponentsInitialization, function () { return _this.populate(); });
_this.bind.oneRootElement(InitializationEvents_1.InitializationEvents.afterInitialization, function () { return _this.handleQueryStateChanged(); });
ResponsiveResultLayout_1.ResponsiveResultLayout.init(_this.root, _this, {});
return _this;
}
Object.defineProperty(ResultLayoutSelector.prototype, "activeLayouts", {
get: function () {
if (this.searchInterface.responsiveComponents.isLargeScreenWidth()) {
return underscore_1.pick(this.currentActiveLayouts, this.options.desktopLayouts);
}
if (this.searchInterface.responsiveComponents.isMediumScreenWidth()) {
return underscore_1.pick(this.currentActiveLayouts, this.options.tabletLayouts);
}
if (this.searchInterface.responsiveComponents.isSmallScreenWidth()) {
return underscore_1.pick(this.currentActiveLayouts, this.options.mobileLayouts);
}
return this.currentActiveLayouts;
},
enumerable: true,
configurable: true
});
/**
* Changes the current layout.
*
* Also logs a `resultLayoutChange` event in the usage analytics with the new layout as metadeta.
*
* Triggers a new query.
*
* @param layout The new layout. The page must contain a valid {@link ResultList} component with a matching
* {@link ResultList.options.layout} value for this method to work.
*/
ResultLayoutSelector.prototype.changeLayout = function (layout) {
this.preferredLayout = null;
this.performLayoutChange(layout);
};
/**
* Gets the current layout (`list`, `card` or `table`).
* @returns {string} The current current layout.
*/
ResultLayoutSelector.prototype.getCurrentLayout = function () {
return this.currentLayout;
};
ResultLayoutSelector.prototype.disableLayouts = function (layouts) {
var _this = this;
if (Utils_1.Utils.isNonEmptyArray(layouts)) {
underscore_1.each(layouts, function (layout) { return _this.disableLayout(layout); });
var remainingValidLayouts = underscore_1.difference(underscore_1.keys(this.currentActiveLayouts), layouts);
this.preferredLayout = this.currentLayout;
if (!underscore_1.isEmpty(remainingValidLayouts)) {
var newLayout = underscore_1.contains(remainingValidLayouts, this.currentLayout) ? this.currentLayout : remainingValidLayouts[0];
this.performLayoutChange(newLayout);
}
else {
this.logger.error('Cannot disable the last valid layout ... Re-enabling the first one possible');
var firstPossibleValidLayout = underscore_1.keys(this.currentActiveLayouts)[0];
this.enableLayout(firstPossibleValidLayout);
this.setLayout(firstPossibleValidLayout);
}
}
};
ResultLayoutSelector.prototype.enableLayouts = function (layouts) {
var _this = this;
underscore_1.each(layouts, function (layout) { return _this.enableLayout(layout); });
var preferredLayoutAvailable = underscore_1.find(layouts, function (layout) { return layout === _this.preferredLayout; });
preferredLayoutAvailable && this.restorePreferredLayout();
};
ResultLayoutSelector.prototype.restorePreferredLayout = function () {
this.performLayoutChange(this.preferredLayout);
this.preferredLayout = null;
};
ResultLayoutSelector.prototype.performLayoutChange = function (layout) {
Assert_1.Assert.check(this.isLayoutDisplayedByButton(layout), 'Layout not available or invalid');
if (layout !== this.currentLayout || this.getModelValue() === '') {
this.setModelValue(layout);
var lastResults = this.queryController.getLastResults();
this.setLayout(layout, lastResults);
if (lastResults) {
this.usageAnalytics.logCustomEvent(AnalyticsActionListMeta_1.analyticsActionCauseList.resultsLayoutChange, {
resultsLayoutChangeTo: layout
}, this.element);
}
else {
this.usageAnalytics.logSearchEvent(AnalyticsActionListMeta_1.analyticsActionCauseList.resultsLayoutChange, {
resultsLayoutChangeTo: layout
});
if (!this.queryController.firstQuery) {
this.queryController.executeQuery();
}
}
}
};
ResultLayoutSelector.prototype.disableLayout = function (layout) {
if (this.isLayoutDisplayedByButton(layout)) {
this.hideButton(layout);
}
};
ResultLayoutSelector.prototype.enableLayout = function (layout) {
var allResultLists = this.resultLists;
var atLeastOneResultListCanShowLayout = underscore_1.find(allResultLists, function (resultList) { return resultList.options.layout == layout; });
if (atLeastOneResultListCanShowLayout && this.isLayoutDisplayedByButton(layout)) {
this.showButton(layout);
this.updateSelectorAppearance();
}
};
Object.defineProperty(ResultLayoutSelector.prototype, "resultLists", {
get: function () {
return this.searchInterface.getComponents('ResultList');
},
enumerable: true,
configurable: true
});
ResultLayoutSelector.prototype.hideButton = function (layout) {
if (this.isLayoutDisplayedByButton(layout)) {
var btn = this.currentActiveLayouts[layout].button;
Dom_1.$$(btn.el).addClass('coveo-hidden');
btn.visible = false;
this.updateSelectorAppearance();
}
};
ResultLayoutSelector.prototype.showButton = function (layout) {
if (this.isLayoutDisplayedByButton(layout)) {
var btn = this.currentActiveLayouts[layout].button;
Dom_1.$$(btn.el).removeClass('coveo-hidden');
btn.visible = true;
}
};
ResultLayoutSelector.prototype.setLayout = function (layout, results) {
if (layout) {
if (this.currentLayout) {
Dom_1.$$(this.currentActiveLayouts[this.currentLayout].button.el).removeClass('coveo-selected');
Dom_1.$$(this.currentActiveLayouts[this.currentLayout].button.el).setAttribute('aria-pressed', false.toString());
}
Dom_1.$$(this.currentActiveLayouts[layout].button.el).addClass('coveo-selected');
Dom_1.$$(this.currentActiveLayouts[layout].button.el).setAttribute('aria-pressed', true.toString());
this.currentLayout = layout;
Dom_1.$$(this.element).trigger(ResultListEvents_1.ResultListEvents.changeLayout, {
layout: layout,
results: results
});
}
};
ResultLayoutSelector.prototype.handleQuerySuccess = function (args) {
this.hasNoResults = args.results.results.length == 0;
if (this.shouldShowSelector()) {
this.show();
}
else {
this.hide();
}
};
ResultLayoutSelector.prototype.handleQueryStateChanged = function (args) {
var modelLayout = this.getModelValue();
var newLayout = underscore_1.find(underscore_1.keys(this.currentActiveLayouts), function (l) { return l === modelLayout; });
if (newLayout !== undefined) {
this.setLayout(newLayout);
}
else {
this.setLayout(underscore_1.keys(this.currentActiveLayouts)[0]);
}
};
ResultLayoutSelector.prototype.handleQueryError = function (args) {
this.hasNoResults = true;
this.hide();
};
ResultLayoutSelector.prototype.updateSelectorAppearance = function () {
if (this.shouldShowSelector()) {
this.show();
}
else {
this.hide();
}
};
ResultLayoutSelector.prototype.populate = function () {
var _this = this;
var populateArgs = { layouts: [] };
Dom_1.$$(this.root).trigger(ResultLayoutEvents_1.ResultLayoutEvents.populateResultLayout, populateArgs);
var layouts = underscore_1.uniq(populateArgs.layouts.map(function (layout) { return layout.toLowerCase(); }));
underscore_1.each(layouts, function (layout) { return Assert_1.Assert.check(underscore_1.contains(ResultLayoutSelector.validLayouts, layout), 'Invalid layout'); });
if (!underscore_1.isEmpty(layouts)) {
underscore_1.each(layouts, function (layout) { return _this.addButton(layout); });
if (!this.shouldShowSelector()) {
this.hide();
}
}
};
ResultLayoutSelector.prototype.addButton = function (layout) {
var _this = this;
var btn = Dom_1.$$('span', {
className: 'coveo-result-layout-selector'
});
var caption = Dom_1.$$('span', { className: 'coveo-result-layout-selector-caption' }, Strings_1.l(layout));
btn.append(caption.el);
var icon = Dom_1.$$('span', { className: "coveo-icon coveo-" + layout + "-layout-icon" }, SVGIcons_1.SVGIcons.icons[layout + "Layout"]);
SVGDom_1.SVGDom.addClassToSVGInContainer(icon.el, "coveo-" + layout + "-svg");
btn.prepend(icon.el);
var selectAction = function () { return _this.changeLayout(layout); };
new AccessibleButton_1.AccessibleButton()
.withElement(btn)
.withLabel(Strings_1.l('DisplayResultsAs', Strings_1.l(layout)))
.withSelectAction(selectAction)
.withOwner(this.bind)
.build();
var isCurrentLayout = layout === this.currentLayout;
btn.toggleClass('coveo-selected', isCurrentLayout);
btn.setAttribute('aria-pressed', isCurrentLayout.toString());
Dom_1.$$(this.element).append(btn.el);
this.currentActiveLayouts[layout] = {
button: {
visible: true,
el: btn.el
},
enabled: true
};
};
ResultLayoutSelector.prototype.hide = function () {
var elem = this.resultLayoutSection || this.element;
Dom_1.$$(elem).addClass('coveo-result-layout-hidden');
};
ResultLayoutSelector.prototype.show = function () {
var elem = this.resultLayoutSection || this.element;
Dom_1.$$(elem).removeClass('coveo-result-layout-hidden');
};
ResultLayoutSelector.prototype.getModelValue = function () {
return this.queryStateModel.get(QueryStateModel_1.QueryStateModel.attributesEnum.layout);
};
ResultLayoutSelector.prototype.setModelValue = function (val) {
this.queryStateModel.set(QueryStateModel_1.QueryStateModel.attributesEnum.layout, val);
};
ResultLayoutSelector.prototype.shouldShowSelector = function () {
return (underscore_1.keys(this.currentActiveLayouts).length > 1 &&
underscore_1.filter(this.currentActiveLayouts, function (activeLayout) { return activeLayout.button.visible; }).length > 1 &&
!this.hasNoResults);
};
ResultLayoutSelector.prototype.isLayoutDisplayedByButton = function (layout) {
return underscore_1.contains(underscore_1.keys(this.currentActiveLayouts), layout);
};
ResultLayoutSelector.ID = 'ResultLayoutSelector';
ResultLayoutSelector.aliases = ['ResultLayout'];
ResultLayoutSelector.doExport = function () {
GlobalExports_1.exportGlobally({
ResultLayoutSelector: ResultLayoutSelector,
ResultLayout: ResultLayoutSelector
});
};
ResultLayoutSelector.validLayouts = ['list', 'card', 'table'];
/**
* The component options
* @componentOptions
*/
ResultLayoutSelector.options = {
/**
* Specifies the layouts that should be available when the search page is displayed in mobile mode.
*
* By default, the mobile mode breakpoint is at 480 px screen width.
*
* To change this default value, use the [responsiveSmallBreakpoint]{@link SearchInterface.options.responsiveSmallBreakpoint} option.
*
* When the breakpoint is reached, layouts that are not specified becomes inactive and the linked result list will be disabled.
*
* The possible values for layouts are `list`, `card`, `table`.
*
* The default value is `card`, `table`.
*/
mobileLayouts: ComponentOptions_1.ComponentOptions.buildListOption({ defaultValue: ['card', 'table'] }),
/**
* Specifies the layouts that should be available when the search page is displayed in tablet mode.
*
* By default, the tablet mode breakpoint is at 800 px screen width.
*
* To change this default value, use the [responsiveMediumBreakpoint]{@link SearchInterface.options.responsiveMediumBreakpoint} option.
*
* When the breakpoint is reached, layouts that are not specified becomes inactive and the linked result list will be disabled.
*
* The possible values for layouts are `list`, `card`, `table`.
*
* The default value is `list`, `card`, `table`.
*/
tabletLayouts: ComponentOptions_1.ComponentOptions.buildListOption({ defaultValue: ['list', 'card', 'table'] }),
/**
* Specifies the layouts that should be available when the search page is displayed in desktop mode.
*
* By default, the desktop mode breakpoint is any screen size over 800 px.
*
* To change this default value, use the [responsiveMediumBreakpoint]{@link SearchInterface.options.responsiveMediumBreakpoint} option.
*
* When the breakpoint is reached, layouts that are not specified becomes inactive and the linked result list will be disabled.
*
* The possible values for layouts are `list`, `card`, `table`.
*
* The default value is `list`, `card`, `table`.
*/
desktopLayouts: ComponentOptions_1.ComponentOptions.buildListOption({ defaultValue: ['list', 'card', 'table'] })
};
return ResultLayoutSelector;
}(Component_1.Component));
exports.ResultLayoutSelector = ResultLayoutSelector;
Initialization_1.Initialization.registerAutoCreateComponent(ResultLayoutSelector);
/***/ }),
/***/ 662:
/***/ (function(module, exports) {
// removed by extract-text-webpack-plugin
/***/ }),
/***/ 663:
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var underscore_1 = __webpack_require__(0);
var Logger_1 = __webpack_require__(9);
var Dom_1 = __webpack_require__(1);
var Component_1 = __webpack_require__(7);
var ResultLayoutSelector_1 = __webpack_require__(201);
var SearchInterface_1 = __webpack_require__(19);
var ResponsiveComponentsManager_1 = __webpack_require__(62);
var ResponsiveResultLayout = /** @class */ (function () {
function ResponsiveResultLayout(coveoRoot, ID, options, responsiveDropdown) {
var _this = this;
this.coveoRoot = coveoRoot;
this.ID = ID;
this.searchInterface = Component_1.Component.get(this.coveoRoot.el, SearchInterface_1.SearchInterface, false);
coveoRoot.on('state:change:t', function () {
_this.handleResizeEvent();
});
}
ResponsiveResultLayout.init = function (root, component, options) {
if (!Dom_1.$$(root).find("." + Component_1.Component.computeCssClassName(ResultLayoutSelector_1.ResultLayoutSelector))) {
var logger = new Logger_1.Logger('ResponsiveResultLayout');
logger.trace('No ResultLayout component found : Cannot instantiate ResponsiveResultLayout');
return;
}
ResponsiveComponentsManager_1.ResponsiveComponentsManager.register(ResponsiveResultLayout, Dom_1.$$(root), ResultLayoutSelector_1.ResultLayoutSelector.ID, component, options);
};
ResponsiveResultLayout.prototype.registerComponent = function (accept) {
if (accept instanceof ResultLayoutSelector_1.ResultLayoutSelector) {
this.resultLayout = accept;
return true;
}
return false;
};
ResponsiveResultLayout.prototype.handleResizeEvent = function () {
if (this.needSmallMode()) {
this.enableAndDisableLayouts(this.resultLayout.options.mobileLayouts);
}
else if (this.needMediumMode()) {
this.enableAndDisableLayouts(this.resultLayout.options.tabletLayouts);
}
else {
this.enableAndDisableLayouts(this.resultLayout.options.desktopLayouts);
}
};
ResponsiveResultLayout.prototype.enableAndDisableLayouts = function (validLayouts) {
var layoutsToDisable = underscore_1.difference(ResultLayoutSelector_1.ResultLayoutSelector.validLayouts, validLayouts);
var layoutsToEnable = underscore_1.intersection(ResultLayoutSelector_1.ResultLayoutSelector.validLayouts, validLayouts);
this.resultLayout.disableLayouts(layoutsToDisable);
this.resultLayout.enableLayouts(layoutsToEnable);
};
ResponsiveResultLayout.prototype.needSmallMode = function () {
switch (this.searchInterface.responsiveComponents.getResponsiveMode()) {
case 'small':
return true;
case 'auto':
return this.coveoRoot.width() <= this.searchInterface.responsiveComponents.getSmallScreenWidth();
default:
return false;
}
};
ResponsiveResultLayout.prototype.needMediumMode = function () {
switch (this.searchInterface.responsiveComponents.getResponsiveMode()) {
case 'medium':
return true;
case 'auto':
return this.coveoRoot.width() <= this.searchInterface.responsiveComponents.getMediumScreenWidth();
default:
return false;
}
};
return ResponsiveResultLayout;
}());
exports.ResponsiveResultLayout = ResponsiveResultLayout;
/***/ })
});
//# sourceMappingURL=ResultLayoutSelector__65d8de8a9f769489e2ff.js.map