coveo-search-ui
Version:
Coveo JavaScript Search Framework
151 lines (134 loc) • 5 kB
text/typescript
///<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;
}
}