Last active
November 28, 2017 18:31
-
-
Save francoislg/f3f174f88f49d8043aa09199490ce030 to your computer and use it in GitHub Desktop.
CoveoFeelingLucky
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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