Skip to content

Instantly share code, notes, and snippets.

@francoislg
Last active November 28, 2017 18:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save francoislg/f3f174f88f49d8043aa09199490ce030 to your computer and use it in GitHub Desktop.
Save francoislg/f3f174f88f49d8043aa09199490ce030 to your computer and use it in GitHub Desktop.
CoveoFeelingLucky
import {
Component,
ComponentOptions,
IComponentBindings,
$$,
QueryEvents,
IDoneBuildingQueryEventArgs,
IBuildingQueryEventArgs,
IRankingFunction,
IFieldOption,
QueryBuilder,
Initialization
} from 'coveo-search-ui';
export interface ICoveoFeelingLuckyOptions {
title: string;
classesToHide: string[];
hiddenComponentClass: string;
randomField: IFieldOption;
maximumRandomRange: number;
numberOfResults: number;
}
export class CoveoFeelingLucky extends Component {
static ID = 'FeelingLucky';
static options: ICoveoFeelingLuckyOptions = {
title: ComponentOptions.buildStringOption(),
classesToHide: ComponentOptions.buildListOption<string>({
defaultValue: ['CoveoPager', 'coveo-sort-section', 'coveo-summary-section']
}),
hiddenComponentClass: ComponentOptions.buildStringOption({
defaultValue: 'hiddenFeelingLucky'
}),
randomField: ComponentOptions.buildFieldOption({
defaultValue: 'randomfield'
}),
maximumRandomRange: ComponentOptions.buildNumberOption({
defaultValue: 1000000
}),
numberOfResults: ComponentOptions.buildNumberOption({
defaultValue: 1
})
};
private feelingLucky: boolean;
constructor(public element: HTMLElement, public options: ICoveoFeelingLuckyOptions, public bindings: IComponentBindings) {
super(element, CoveoFeelingLucky.ID, bindings);
this.options = ComponentOptions.initComponentOptions(element, CoveoFeelingLucky, options);
this.feelingLucky = false;
this.buildDomContent();
this.element.addEventListener('click', () => this.handleClickEvent());
this.bind.onRootElement(QueryEvents.buildingQuery, (args: IBuildingQueryEventArgs) => this.handleBuildingQuery(args));
this.bind.onRootElement(QueryEvents.doneBuildingQuery, (args: IDoneBuildingQueryEventArgs) => this.handleDoneBuildingQuery(args));
}
public toggle(): void {
this.feelingLucky = !this.feelingLucky;
this.element.classList.toggle('selected');
this.hideElementsWithClassesToHide();
this.searchInterface.queryController.executeQuery();
}
public getCurrentState(): boolean {
return this.feelingLucky;
}
private handleClickEvent(): void {
this.toggle();
}
private buildDomContent(): void {
if (typeof(this.options.title) !== 'undefined' && this.options.title != '') {
this.element.appendChild(this.createTitleChild());
}
}
private createTitleChild(): HTMLElement {
const title = document.createElement('span');
title.innerHTML = this.options.title;
return title;
}
private hideElementsWithClassesToHide(): void {
const selector = this.options.classesToHide
.map(classToHide => `.${classToHide}`)
.join(', ');
const elements = this.root.querySelectorAll(selector);
for (let i = 0, length = elements.length; i < length; i++) {
elements[i].classList.toggle(this.options.hiddenComponentClass);
}
}
private handleBuildingQuery(args: IBuildingQueryEventArgs): void {
if (this.isFeelingLucky()) {
this.applyFeelingLuckyToQueryBuilder(args.queryBuilder, this.options.randomField, this.options.maximumRandomRange);
}
}
private applyFeelingLuckyToQueryBuilder(queryBuilder: QueryBuilder,
randomField: IFieldOption,
maximumRandomRange: number): void {
const randomNumber = Math.floor(Math.random() * maximumRandomRange);
// Create a ranking expression, shifting every randomField value to a random number, and wrapping them with the maximum range.
// This ensures that we have different results every time.
const rankingFunction: IRankingFunction = {
expression: `(@${randomField} + ${randomNumber}) % ${maximumRandomRange}`,
normalizeWeight: false,
};
queryBuilder.rankingFunctions.push(rankingFunction);
// Adds @randomField to the expression to ensure the results have the required field.
queryBuilder.advancedExpression.add(`@${randomField}`);
// Use the empty pipeline to remove Featured Results, Automatic Ranking, and all the other pipeline features.
queryBuilder.pipeline = '';
queryBuilder.sortCriteria = 'relevancy';
queryBuilder.maximumAge = 0;
}
private handleDoneBuildingQuery(args: IDoneBuildingQueryEventArgs): void {
if (this.isFeelingLucky()) {
args.queryBuilder.numberOfResults = this.options.numberOfResults;
}
}
private isFeelingLucky(): boolean {
return this.feelingLucky;
}
}
Initialization.registerAutoCreateComponent(CoveoFeelingLucky);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment