You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
devdocs/assets/javascripts/views/search/search.js

225 lines
6.1 KiB

/*
* decaffeinate suggestions:
* DS002: Fix invalid constructor
* DS102: Remove unnecessary code created because of implicit returns
* DS103: Rewrite code to no longer use __guard__, or convert again using --optional-chaining
* DS206: Consider reworking classes to avoid initClass
* DS207: Consider shorter variations of null checks
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
*/
(function() {
let SEARCH_PARAM = undefined;
let HASH_RGX = undefined;
const Cls = (app.views.Search = class Search extends app.View {
constructor(...args) {
this.focus = this.focus.bind(this);
this.autoFocus = this.autoFocus.bind(this);
this.onWindowFocus = this.onWindowFocus.bind(this);
this.onReady = this.onReady.bind(this);
this.onInput = this.onInput.bind(this);
this.searchUrl = this.searchUrl.bind(this);
this.google = this.google.bind(this);
this.stackoverflow = this.stackoverflow.bind(this);
this.duckduckgo = this.duckduckgo.bind(this);
this.onResults = this.onResults.bind(this);
this.onEnd = this.onEnd.bind(this);
this.onClick = this.onClick.bind(this);
this.onScopeChange = this.onScopeChange.bind(this);
this.afterRoute = this.afterRoute.bind(this);
super(...args);
}
static initClass() {
SEARCH_PARAM = app.config.search_param;
this.el = '._search';
this.activeClass = '_search-active';
this.elements = {
input: '._search-input',
resetLink: '._search-clear'
};
this.events = {
input: 'onInput',
click: 'onClick',
submit: 'onSubmit'
};
this.shortcuts = {
typing: 'focus',
altG: 'google',
altS: 'stackoverflow',
altD: 'duckduckgo'
};
this.routes =
{after: 'afterRoute'};
HASH_RGX = new RegExp(`^#${SEARCH_PARAM}=(.*)`);
}
init() {
this.addSubview(this.scope = new app.views.SearchScope(this.el));
this.searcher = new app.Searcher;
this.searcher
.on('results', this.onResults)
.on('end', this.onEnd);
this.scope
.on('change', this.onScopeChange);
app.on('ready', this.onReady);
$.on(window, 'hashchange', this.searchUrl);
$.on(window, 'focus', this.onWindowFocus);
}
focus() {
if (document.activeElement === this.input) { return; }
if (app.settings.get('noAutofocus')) { return; }
this.input.focus();
}
autoFocus() {
if (app.isMobile() || $.isAndroid() || $.isIOS()) { return; }
if ((document.activeElement != null ? document.activeElement.tagName : undefined) === 'INPUT') { return; }
if (app.settings.get('noAutofocus')) { return; }
this.input.focus();
}
onWindowFocus(event) {
if (event.target === window) { return this.autoFocus(); }
}
getScopeDoc() {
if (this.scope.isActive()) { return this.scope.getScope(); }
}
reset(force) {
if (force || !this.input.value) { this.scope.reset(); }
this.el.reset();
this.onInput();
this.autoFocus();
}
onReady() {
this.value = '';
this.delay(this.onInput);
}
onInput() {
if ((this.value == null) || // ignore events pre-"ready"
(this.value === this.input.value)) { return; }
this.value = this.input.value;
if (this.value.length) {
this.search();
} else {
this.clear();
}
}
search(url) {
if (url == null) { url = false; }
this.addClass(this.constructor.activeClass);
this.trigger('searching');
this.hasResults = null;
this.flags = {urlSearch: url, initialResults: true};
this.searcher.find(this.scope.getScope().entries.all(), 'text', this.value);
}
searchUrl() {
let value;
if (location.pathname === '/') {
this.scope.searchUrl();
} else if (!app.router.isIndex()) {
return;
}
if (!(value = this.extractHashValue())) { return; }
this.input.value = (this.value = value);
this.input.setSelectionRange(value.length, value.length);
this.search(true);
return true;
}
clear() {
this.removeClass(this.constructor.activeClass);
this.trigger('clear');
}
externalSearch(url) {
let value;
if (value = this.value) {
if (this.scope.name()) { value = `${this.scope.name()} ${value}`; }
$.popup(`${url}${encodeURIComponent(value)}`);
this.reset();
}
}
google() {
this.externalSearch("https://www.google.com/search?q=");
}
stackoverflow() {
this.externalSearch("https://stackoverflow.com/search?q=");
}
duckduckgo() {
this.externalSearch("https://duckduckgo.com/?t=devdocs&q=");
}
onResults(results) {
if (results.length) { this.hasResults = true; }
this.trigger('results', results, this.flags);
this.flags.initialResults = false;
}
onEnd() {
if (!this.hasResults) { this.trigger('noresults'); }
}
onClick(event) {
if (event.target === this.resetLink) {
$.stopEvent(event);
this.reset();
}
}
onSubmit(event) {
$.stopEvent(event);
}
onScopeChange() {
this.value = '';
this.onInput();
}
afterRoute(name, context) {
if ((app.shortcuts.eventInProgress != null ? app.shortcuts.eventInProgress.name : undefined) === 'escape') { return; }
if (!context.init && app.router.isIndex()) { this.reset(true); }
if (context.hash) { this.delay(this.searchUrl); }
$.requestAnimationFrame(this.autoFocus);
}
extractHashValue() {
let value;
if ((value = this.getHashValue()) != null) {
app.router.replaceHash();
return value;
}
}
getHashValue() {
try { return __guard__(HASH_RGX.exec($.urlDecode(location.hash)), x => x[1]); } catch (error) {}
}
});
Cls.initClass();
return Cls;
})();
function __guard__(value, transform) {
return (typeof value !== 'undefined' && value !== null) ? transform(value) : undefined;
}