UNPKG

coveo-search-ui

Version:

Coveo JavaScript Search Framework

151 lines (134 loc) 5 kB
///<reference path='Omnibox.ts'/> import { OmniboxEvents, IPopulateOmniboxSuggestionsEventArgs } from '../../events/OmniboxEvents'; import { Omnibox, IOmniboxSuggestion } from './Omnibox'; import { IExtension } from '../../rest/Extension'; import * as _ from 'underscore'; import { MagicBoxInstance } from '../../magicbox/MagicBox'; import { MagicBoxUtils } from '../../magicbox/MagicBoxUtils'; import { Result } from '../../magicbox/Result/Result'; interface IQueryExtensionAddonHash { type: string; before: string; after: string; current: string; name?: string; used?: string[]; } export class QueryExtensionAddon { static INDEX = 62; cache: { [hash: string]: Promise<string[]> } = {}; constructor(public omnibox: Omnibox) { this.omnibox.bind.on(this.omnibox.element, OmniboxEvents.populateOmniboxSuggestions, (args: IPopulateOmniboxSuggestionsEventArgs) => { args.suggestions.push(this.getSuggestion()); }); } public getSuggestion(): Promise<IOmniboxSuggestion[]> { var hash = this.getHash(this.omnibox.magicBox); if (hash == null) { return null; } var hashString = this.hashToString(hash); if (this.cache[hashString] != null) { return this.hashValueToSuggestion(hash, this.cache[hashString]); } var values = hash.type == 'QueryExtensionName' ? this.names(hash.current) : this.attributeNames(hash.name, hash.current, hash.used); this.cache[hashString] = values; values.catch(() => { delete this.cache[hashString]; }); return this.hashValueToSuggestion(hash, values); } private getHash(magicBox: MagicBoxInstance): IQueryExtensionAddonHash { var queryExtension: Result = _.last(magicBox.resultAtCursor('QueryExtension')); if (queryExtension != null) { var queryExtensionArgumentResults = queryExtension.findAll('QueryExtensionArgument'); var current = _.last(magicBox.resultAtCursor('QueryExtensionName')); if (current != null) { return { type: 'QueryExtensionName', current: current.toString(), before: current.before(), after: current.after() }; } current = _.last(magicBox.resultAtCursor('QueryExtensionArgumentName')); if (current != null) { var used: string[] = _.chain(queryExtensionArgumentResults) .map(result => { var name = result.find('QueryExtensionArgumentName'); return name && name.toString(); }) .compact() .value(); var name = queryExtension.find('QueryExtensionName').toString(); return { type: 'QueryExtensionArgumentName', current: current.toString(), before: current.before(), after: current.after(), name: name, used: used }; } } return null; } private hashToString(hash: IQueryExtensionAddonHash) { if (hash == null) { return null; } return [hash.type, hash.current, hash.name || '', hash.used ? hash.used.join() : ''].join(); } private hashValueToSuggestion(hash: IQueryExtensionAddonHash, promise: Promise<string[]>): Promise<IOmniboxSuggestion[]> { return promise.then(values => { var suggestions: IOmniboxSuggestion[] = _.map(values, (value, i) => { return { html: MagicBoxUtils.highlightText(value, hash.current, true), text: hash.before + value + hash.after, index: QueryExtensionAddon.INDEX - i / values.length }; }); return suggestions; }); } private extensions: Promise<any>; private getExtensions() { if (this.extensions == null) { this.extensions = this.omnibox.queryController.getEndpoint().extensions(); } return this.extensions; } private names(current: string): Promise<string[]> { var extensionName = current.toLowerCase(); return this.getExtensions().then((extensions: IExtension[]) => { var matchExtensions = _.chain(extensions) .map((extension: IExtension) => { return { index: extension.name.toLowerCase().indexOf(extensionName), extension: extension.name }; }) .filter(extension => { return extension.index != -1 && extension.extension.length > extensionName.length; }) .sortBy('index') .pluck('extension') .value(); matchExtensions = _.first(matchExtensions, 5); return matchExtensions; }); } private attributeNames(name: string, current: string, used: string[]): Promise<string[]> { return this.getExtensions().then((extensions: IExtension[]) => { var extension = _.find(extensions, (extension: IExtension) => extension.name == name); if (extension == null) { return []; } else { return _.filter(_.difference(extension.argumentNames, used), (argumentName: string) => argumentName.indexOf(current) == 0); } }); } public hash() { return; } }