168 lines
4.0 KiB
JavaScript
168 lines
4.0 KiB
JavaScript
class Influencer {
|
|
constructor(options) {
|
|
this._limit = options.limit;
|
|
this._parseQuery = options.parseQuery;
|
|
}
|
|
|
|
addItem() {}
|
|
getSuggestions() {}
|
|
|
|
_addSearchPrefix(items, query) {
|
|
const searchPrefix = this._getSearchPrefix(query);
|
|
return items.map(s => (searchPrefix ? searchPrefix + s : s));
|
|
}
|
|
|
|
_getSearchPrefix(query) {
|
|
const { isSearch, key, split } = this._parseQuery(query);
|
|
return isSearch ? `${key}${split} ` : false;
|
|
}
|
|
}
|
|
|
|
class DefaultInfluencer extends Influencer {
|
|
constructor({ defaultSuggestions }) {
|
|
super(...arguments);
|
|
this._defaultSuggestions = defaultSuggestions;
|
|
}
|
|
|
|
getSuggestions(query) {
|
|
return new Promise(resolve => {
|
|
const suggestions = this._defaultSuggestions[query];
|
|
resolve(suggestions ? suggestions.slice(0, this._limit) : []);
|
|
});
|
|
}
|
|
}
|
|
|
|
|
|
class CommandsInfluencer extends Influencer {
|
|
constructor({ commands, queryParser }) {
|
|
super(...arguments);
|
|
this._commands = commands;
|
|
}
|
|
|
|
getSuggestions(rawQuery) {
|
|
const { query } = this._parseQuery(rawQuery);
|
|
if (!query) return Promise.resolve([]);
|
|
|
|
return new Promise(resolve => {
|
|
const suggestions = [];
|
|
const commands = this._commands;
|
|
|
|
commands.forEach(command => {
|
|
if(this._getDomain(command.url).startsWith(rawQuery)){
|
|
suggestions.push(command.url);
|
|
}
|
|
});
|
|
|
|
resolve(suggestions);
|
|
});
|
|
}
|
|
|
|
_getHostName(url) {
|
|
let match = url.match(/:\/\/(www[0-9]?\.)?(.[^/:]+)/i);
|
|
if (match != null && match.length > 2 && typeof match[2] === 'string' && match[2].length > 0) {
|
|
return match[2];
|
|
}
|
|
else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
_getDomain(url){
|
|
let hostName = this._getHostName(url);
|
|
let domain = hostName;
|
|
|
|
if (hostName != null) {
|
|
let parts = hostName.split('.').reverse();
|
|
if (parts != null && parts.length > 1) {
|
|
domain = parts[1] + '.' + parts[0];
|
|
if (hostName.toLowerCase().indexOf('.co.uk') != -1 && parts.length > 2) {
|
|
domain = parts[2] + '.' + domain;
|
|
}
|
|
}
|
|
}
|
|
|
|
return domain;
|
|
}
|
|
}
|
|
|
|
class DuckDuckGoInfluencer extends Influencer {
|
|
constructor({ queryParser }) {
|
|
super(...arguments);
|
|
}
|
|
|
|
getSuggestions(rawQuery) {
|
|
const { query } = this._parseQuery(rawQuery);
|
|
if (!query) return Promise.resolve([]);
|
|
|
|
return new Promise(resolve => {
|
|
const endpoint = 'https://duckduckgo.com/ac/';
|
|
const callback = 'autocompleteCallback';
|
|
|
|
window[callback] = res => {
|
|
const suggestions = res
|
|
.map(i => i.phrase)
|
|
.filter(s => !$.ieq(s, query))
|
|
.slice(0, this._limit);
|
|
|
|
resolve(this._addSearchPrefix(suggestions, rawQuery));
|
|
};
|
|
|
|
$.jsonp(`${endpoint}?callback=${callback}&q=${query}`);
|
|
});
|
|
}
|
|
}
|
|
|
|
class HistoryInfluencer extends Influencer {
|
|
constructor() {
|
|
super(...arguments);
|
|
this._storeName = 'history';
|
|
}
|
|
|
|
addItem(query) {
|
|
if (query.length < 2) return;
|
|
let exists;
|
|
|
|
const history = this._getHistory().map(([item, count]) => {
|
|
const match = $.ieq(item, query);
|
|
if (match) exists = true;
|
|
return [item, match ? count + 1 : count];
|
|
});
|
|
|
|
if (!exists) history.push([query, 1]);
|
|
|
|
const sorted = history
|
|
.sort((current, next) => current[1] - next[1])
|
|
.reverse();
|
|
|
|
this._setHistory(sorted);
|
|
}
|
|
|
|
getSuggestions(query) {
|
|
return new Promise(resolve => {
|
|
const suggestions = this._getHistory()
|
|
.map(([item]) => item)
|
|
.filter(item => query && !$.ieq(item, query) && $.iin(item, query))
|
|
.slice(0, this._limit);
|
|
|
|
resolve(suggestions);
|
|
});
|
|
}
|
|
|
|
_fetch() {
|
|
return JSON.parse(localStorage.getItem(this._storeName)) || [];
|
|
}
|
|
|
|
_getHistory() {
|
|
this._history = this._history || this._fetch();
|
|
return this._history;
|
|
}
|
|
|
|
_save(history) {
|
|
localStorage.setItem(this._storeName, JSON.stringify(history));
|
|
}
|
|
|
|
_setHistory(history) {
|
|
this._history = history;
|
|
this._save(history);
|
|
}
|
|
} |