History

Sanity-check decaffeinate app.views.Search

Simon Legner committed 2 years ago

Commit bbadf5f1 parent cf412bd1 file · +177 −216Browse files

Unified · Split

assets/javascripts/views/search/search.js+177−216
@@ -1,261 +1,222 @@
1// TODO: This file was created by bulk-decaffeinate.1app.views.Search = class Search extends app.View {
2// Sanity-check the conversion and remove this comment.2 static SEARCH_PARAM = app.config.search_param;
3/*
4 * decaffeinate suggestions:
5 * DS102: Remove unnecessary code created because of implicit returns
6 * DS103: Rewrite code to no longer use __guard__, or convert again using --optional-chaining
7 * DS206: Consider reworking classes to avoid initClass
8 * DS207: Consider shorter variations of null checks
9 * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
10 */
11(function () {
12 let SEARCH_PARAM = undefined;
13 let HASH_RGX = undefined;
14 app.views.Search = class Search extends app.View {
15 static initClass() {
16 SEARCH_PARAM = app.config.search_param;
17
18 this.el = "._search";
19 this.activeClass = "_search-active";
20
21 this.elements = {
22 input: "._search-input",
23 resetLink: "._search-clear",
24 };
25
26 this.events = {
27 input: "onInput",
28 click: "onClick",
29 submit: "onSubmit",
30 };
31
32 this.shortcuts = {
33 typing: "focus",
34 altG: "google",
35 altS: "stackoverflow",
36 altD: "duckduckgo",
37 };
38
39 this.routes = { after: "afterRoute" };
40
41 HASH_RGX = new RegExp(`^#${SEARCH_PARAM}=(.*)`);
42 }
43 3
44 init() {4 static el = "._search";
45 this.addSubview((this.scope = new app.views.SearchScope(this.el)));5 static activeClass = "_search-active";
46 6
47 this.searcher = new app.Searcher();7 static elements = {
48 this.searcher8 input: "._search-input",
49 .on("results", (results) => this.onResults(results))9 resetLink: "._search-clear",
50 .on("end", () => this.onEnd());10 };
51 11
52 this.scope.on("change", () => this.onScopeChange());12 static events = {
13 input: "onInput",
14 click: "onClick",
15 submit: "onSubmit",
16 };
53 17
54 app.on("ready", () => this.onReady());18 static shortcuts = {
55 $.on(window, "hashchange", () => this.searchUrl());19 typing: "focus",
56 $.on(window, "focus", (event) => this.onWindowFocus(event));20 altG: "google",
57 }21 altS: "stackoverflow",
22 altD: "duckduckgo",
23 };
58 24
59 focus() {25 static routes = { after: "afterRoute" };
60 if (document.activeElement === this.input) {
61 return;
62 }
63 if (app.settings.get("noAutofocus")) {
64 return;
65 }
66 this.input.focus();
67 }
68 26
69 autoFocus() {27 static HASH_RGX = new RegExp(`^#${Search.SEARCH_PARAM}=(.*)`);
70 if (app.isMobile() || $.isAndroid() || $.isIOS()) {
71 return;
72 }
73 if (
74 (document.activeElement != null
75 ? document.activeElement.tagName
76 : undefined) === "INPUT"
77 ) {
78 return;
79 }
80 if (app.settings.get("noAutofocus")) {
81 return;
82 }
83 this.input.focus();
84 }
85 28
86 onWindowFocus(event) {29 init() {
87 if (event.target === window) {30 this.addSubview((this.scope = new app.views.SearchScope(this.el)));
88 return this.autoFocus();
89 }
90 }
91 31
92 getScopeDoc() {32 this.searcher = new app.Searcher();
93 if (this.scope.isActive()) {33 this.searcher
94 return this.scope.getScope();34 .on("results", (results) => this.onResults(results))
95 }35 .on("end", () => this.onEnd());
96 }
97 36
98 reset(force) {37 this.scope.on("change", () => this.onScopeChange());
99 if (force || !this.input.value) {38
100 this.scope.reset();39 app.on("ready", () => this.onReady());
101 }40 $.on(window, "hashchange", () => this.searchUrl());
102 this.el.reset();41 $.on(window, "focus", (event) => this.onWindowFocus(event));
103 this.onInput();42 }
104 this.autoFocus();43
44 focus() {
45 if (document.activeElement === this.input) {
46 return;
47 }
48 if (app.settings.get("noAutofocus")) {
49 return;
105 }50 }
51 this.input.focus();
52 }
106 53
107 onReady() {54 autoFocus() {
108 this.value = "";55 if (app.isMobile() || $.isAndroid() || $.isIOS()) {
109 this.delay(this.onInput);56 return;
57 }
58 if (document.activeElement?.tagName === "INPUT") {
59 return;
110 }60 }
61 if (app.settings.get("noAutofocus")) {
62 return;
63 }
64 this.input.focus();
65 }
111 66
112 onInput() {67 onWindowFocus(event) {
113 if (68 if (event.target === window) {
114 this.value == null || // ignore events pre-"ready"69 return this.autoFocus();
115 this.value === this.input.value70 }
116 ) {71 }
117 return;
118 }
119 this.value = this.input.value;
120 72
121 if (this.value.length) {73 getScopeDoc() {
122 this.search();74 if (this.scope.isActive()) {
123 } else {75 return this.scope.getScope();
124 this.clear();
125 }
126 }76 }
77 }
127 78
128 search(url) {79 reset(force) {
129 if (url == null) {80 if (force || !this.input.value) {
130 url = false;81 this.scope.reset();
131 }
132 this.addClass(this.constructor.activeClass);
133 this.trigger("searching");
134
135 this.hasResults = null;
136 this.flags = { urlSearch: url, initialResults: true };
137 this.searcher.find(
138 this.scope.getScope().entries.all(),
139 "text",
140 this.value,
141 );
142 }82 }
83 this.el.reset();
84 this.onInput();
85 this.autoFocus();
86 }
143 87
144 searchUrl() {88 onReady() {
145 let value;89 this.value = "";
146 if (location.pathname === "/") {90 this.delay(this.onInput);
147 this.scope.searchUrl();91 }
148 } else if (!app.router.isIndex()) {
149 return;
150 }
151 92
152 if (!(value = this.extractHashValue())) {93 onInput() {
153 return;94 if (
154 }95 this.value == null || // ignore events pre-"ready"
155 this.input.value = this.value = value;96 this.value === this.input.value
156 this.input.setSelectionRange(value.length, value.length);97 ) {
157 this.search(true);98 return;
158 return true;
159 }99 }
100 this.value = this.input.value;
160 101
161 clear() {102 if (this.value.length) {
162 this.removeClass(this.constructor.activeClass);103 this.search();
163 this.trigger("clear");104 } else {
105 this.clear();
164 }106 }
107 }
165 108
166 externalSearch(url) {109 search(url) {
167 let value;110 if (url == null) {
168 if ((value = this.value)) {111 url = false;
169 if (this.scope.name()) {
170 value = `${this.scope.name()} ${value}`;
171 }
172 $.popup(`${url}${encodeURIComponent(value)}`);
173 this.reset();
174 }
175 }112 }
113 this.addClass(this.constructor.activeClass);
114 this.trigger("searching");
176 115
177 google() {116 this.hasResults = null;
178 this.externalSearch("https://www.google.com/search?q=");117 this.flags = { urlSearch: url, initialResults: true };
179 }118 this.searcher.find(this.scope.getScope().entries.all(), "text", this.value);
119 }
180 120
181 stackoverflow() {121 searchUrl() {
182 this.externalSearch("https://stackoverflow.com/search?q=");122 let value;
123 if (location.pathname === "/") {
124 this.scope.searchUrl();
125 } else if (!app.router.isIndex()) {
126 return;
183 }127 }
184 128
185 duckduckgo() {129 if (!(value = this.extractHashValue())) {
186 this.externalSearch("https://duckduckgo.com/?t=devdocs&q=");130 return;
187 }131 }
132 this.input.value = this.value = value;
133 this.input.setSelectionRange(value.length, value.length);
134 this.search(true);
135 return true;
136 }
137
138 clear() {
139 this.removeClass(this.constructor.activeClass);
140 this.trigger("clear");
141 }
188 142
189 onResults(results) {143 externalSearch(url) {
190 if (results.length) {144 let value;
191 this.hasResults = true;145 if ((value = this.value)) {
146 if (this.scope.name()) {
147 value = `${this.scope.name()} ${value}`;
192 }148 }
193 this.trigger("results", results, this.flags);149 $.popup(`${url}${encodeURIComponent(value)}`);
194 this.flags.initialResults = false;150 this.reset();
195 }151 }
152 }
196 153
197 onEnd() {154 google() {
198 if (!this.hasResults) {155 this.externalSearch("https://www.google.com/search?q=");
199 this.trigger("noresults");156 }
200 }157
158 stackoverflow() {
159 this.externalSearch("https://stackoverflow.com/search?q=");
160 }
161
162 duckduckgo() {
163 this.externalSearch("https://duckduckgo.com/?t=devdocs&q=");
164 }
165
166 onResults(results) {
167 if (results.length) {
168 this.hasResults = true;
201 }169 }
170 this.trigger("results", results, this.flags);
171 this.flags.initialResults = false;
172 }
202 173
203 onClick(event) {174 onEnd() {
204 if (event.target === this.resetLink) {175 if (!this.hasResults) {
205 $.stopEvent(event);176 this.trigger("noresults");
206 this.reset();
207 }
208 }177 }
178 }
209 179
210 onSubmit(event) {180 onClick(event) {
181 if (event.target === this.resetLink) {
211 $.stopEvent(event);182 $.stopEvent(event);
183 this.reset();
212 }184 }
185 }
213 186
214 onScopeChange() {187 onSubmit(event) {
215 this.value = "";188 $.stopEvent(event);
216 this.onInput();189 }
217 }
218 190
219 afterRoute(name, context) {191 onScopeChange() {
220 if (192 this.value = "";
221 (app.shortcuts.eventInProgress != null193 this.onInput();
222 ? app.shortcuts.eventInProgress.name194 }
223 : undefined) === "escape"
224 ) {
225 return;
226 }
227 if (!context.init && app.router.isIndex()) {
228 this.reset(true);
229 }
230 if (context.hash) {
231 this.delay(this.searchUrl);
232 }
233 $.requestAnimationFrame(() => this.autoFocus());
234 }
235 195
236 extractHashValue() {196 afterRoute(name, context) {
237 let value;197 if (app.shortcuts.eventInProgress?.name === "escape") {
238 if ((value = this.getHashValue()) != null) {198 return;
239 app.router.replaceHash();199 }
240 return value;200 if (!context.init && app.router.isIndex()) {
241 }201 this.reset(true);
202 }
203 if (context.hash) {
204 this.delay(this.searchUrl);
242 }205 }
206 $.requestAnimationFrame(() => this.autoFocus());
207 }
243 208
244 getHashValue() {209 extractHashValue() {
245 try {210 let value = this.getHashValue();
246 return __guard__(211 if (value != null) {
247 HASH_RGX.exec($.urlDecode(location.hash)),212 app.router.replaceHash();
248 (x) => x[1],213 return value;
249 );
250 } catch (error) {}
251 }214 }
252 };215 }
253 app.views.Search.initClass();216
254 return app.views.Search;217 getHashValue() {
255})();218 try {
256 219 return Search.HASH_RGX.exec($.urlDecode(location.hash))?.[1];
257function __guard__(value, transform) {220 } catch (error) {}
258 return typeof value !== "undefined" && value !== null221 }
259 ? transform(value)222};
260 : undefined;
261}