Unified · Split
| @@ -1,207 +1,180 @@ | |||
| 1 | // TODO: This file was created by bulk-decaffeinate. | 1 | app.views.SearchScope = class SearchScope 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.SearchScope = class SearchScope extends app.View { | ||
| 15 | static initClass() { | ||
| 16 | SEARCH_PARAM = app.config.search_param; | ||
| 17 | |||
| 18 | this.elements = { | ||
| 19 | input: "._search-input", | ||
| 20 | tag: "._search-tag", | ||
| 21 | }; | ||
| 22 | |||
| 23 | this.events = { | ||
| 24 | click: "onClick", | ||
| 25 | keydown: "onKeydown", | ||
| 26 | textInput: "onTextInput", | ||
| 27 | }; | ||
| 28 | |||
| 29 | this.routes = { after: "afterRoute" }; | ||
| 30 | |||
| 31 | HASH_RGX = new RegExp(`^#${SEARCH_PARAM}=(.+?) .`); | ||
| 32 | } | ||
| 33 | 3 | ||
| 34 | init() { | 4 | static elements = { |
| 35 | this.placeholder = this.input.getAttribute("placeholder"); | 5 | input: "._search-input", |
| 6 | tag: "._search-tag", | ||
| 7 | }; | ||
| 36 | 8 | ||
| 37 | this.searcher = new app.SynchronousSearcher({ | 9 | static events = { |
| 38 | fuzzy_min_length: 2, | 10 | click: "onClick", |
| 39 | max_results: 1, | 11 | keydown: "onKeydown", |
| 40 | }); | 12 | textInput: "onTextInput", |
| 41 | this.searcher.on("results", (results) => this.onResults(results)); | 13 | }; |
| 42 | } | ||
| 43 | 14 | ||
| 44 | getScope() { | 15 | static routes = { after: "afterRoute" }; |
| 45 | return this.doc || app; | ||
| 46 | } | ||
| 47 | 16 | ||
| 48 | isActive() { | 17 | static HASH_RGX = new RegExp(`^#${SearchScope.SEARCH_PARAM}=(.+?) .`); |
| 49 | return !!this.doc; | 18 | |
| 50 | } | 19 | init() { |
| 20 | this.placeholder = this.input.getAttribute("placeholder"); | ||
| 21 | |||
| 22 | this.searcher = new app.SynchronousSearcher({ | ||
| 23 | fuzzy_min_length: 2, | ||
| 24 | max_results: 1, | ||
| 25 | }); | ||
| 26 | this.searcher.on("results", (results) => this.onResults(results)); | ||
| 27 | } | ||
| 28 | |||
| 29 | getScope() { | ||
| 30 | return this.doc || app; | ||
| 31 | } | ||
| 32 | |||
| 33 | isActive() { | ||
| 34 | return !!this.doc; | ||
| 35 | } | ||
| 51 | 36 | ||
| 52 | name() { | 37 | name() { |
| 53 | return this.doc != null ? this.doc.name : undefined; | 38 | return this.doc != null ? this.doc.name : undefined; |
| 39 | } | ||
| 40 | |||
| 41 | search(value, searchDisabled) { | ||
| 42 | if (searchDisabled == null) { | ||
| 43 | searchDisabled = false; | ||
| 44 | } | ||
| 45 | if (this.doc) { | ||
| 46 | return; | ||
| 47 | } | ||
| 48 | this.searcher.find(app.docs.all(), "text", value); | ||
| 49 | if (!this.doc && searchDisabled) { | ||
| 50 | this.searcher.find(app.disabledDocs.all(), "text", value); | ||
| 54 | } | 51 | } |
| 52 | } | ||
| 55 | 53 | ||
| 56 | search(value, searchDisabled) { | 54 | searchUrl() { |
| 57 | if (searchDisabled == null) { | 55 | let value; |
| 58 | searchDisabled = false; | 56 | if ((value = this.extractHashValue())) { |
| 59 | } | 57 | this.search(value, true); |
| 60 | if (this.doc) { | ||
| 61 | return; | ||
| 62 | } | ||
| 63 | this.searcher.find(app.docs.all(), "text", value); | ||
| 64 | if (!this.doc && searchDisabled) { | ||
| 65 | this.searcher.find(app.disabledDocs.all(), "text", value); | ||
| 66 | } | ||
| 67 | } | 58 | } |
| 59 | } | ||
| 68 | 60 | ||
| 69 | searchUrl() { | 61 | onResults(results) { |
| 70 | let value; | 62 | let doc; |
| 71 | if ((value = this.extractHashValue())) { | 63 | if (!(doc = results[0])) { |
| 72 | this.search(value, true); | 64 | return; |
| 73 | } | ||
| 74 | } | 65 | } |
| 66 | if (app.docs.contains(doc)) { | ||
| 67 | this.selectDoc(doc); | ||
| 68 | } else { | ||
| 69 | this.redirectToDoc(doc); | ||
| 70 | } | ||
| 71 | } | ||
| 75 | 72 | ||
| 76 | onResults(results) { | 73 | selectDoc(doc) { |
| 77 | let doc; | 74 | const previousDoc = this.doc; |
| 78 | if (!(doc = results[0])) { | 75 | if (doc === previousDoc) { |
| 79 | return; | 76 | return; |
| 80 | } | ||
| 81 | if (app.docs.contains(doc)) { | ||
| 82 | this.selectDoc(doc); | ||
| 83 | } else { | ||
| 84 | this.redirectToDoc(doc); | ||
| 85 | } | ||
| 86 | } | 77 | } |
| 78 | this.doc = doc; | ||
| 87 | 79 | ||
| 88 | selectDoc(doc) { | 80 | this.tag.textContent = doc.fullName; |
| 89 | const previousDoc = this.doc; | 81 | this.tag.style.display = "block"; |
| 90 | if (doc === previousDoc) { | ||
| 91 | return; | ||
| 92 | } | ||
| 93 | this.doc = doc; | ||
| 94 | 82 | ||
| 95 | this.tag.textContent = doc.fullName; | 83 | this.input.removeAttribute("placeholder"); |
| 96 | this.tag.style.display = "block"; | 84 | this.input.value = this.input.value.slice(this.input.selectionStart); |
| 85 | this.input.style.paddingLeft = this.tag.offsetWidth + 10 + "px"; | ||
| 97 | 86 | ||
| 98 | this.input.removeAttribute("placeholder"); | 87 | $.trigger(this.input, "input"); |
| 99 | this.input.value = this.input.value.slice(this.input.selectionStart); | 88 | this.trigger("change", this.doc, previousDoc); |
| 100 | this.input.style.paddingLeft = this.tag.offsetWidth + 10 + "px"; | 89 | } |
| 101 | 90 | ||
| 102 | $.trigger(this.input, "input"); | 91 | redirectToDoc(doc) { |
| 103 | this.trigger("change", this.doc, previousDoc); | 92 | const { hash } = location; |
| 104 | } | 93 | app.router.replaceHash(""); |
| 94 | location.assign(doc.fullPath() + hash); | ||
| 95 | } | ||
| 105 | 96 | ||
| 106 | redirectToDoc(doc) { | 97 | reset() { |
| 107 | const { hash } = location; | 98 | if (!this.doc) { |
| 108 | app.router.replaceHash(""); | 99 | return; |
| 109 | location.assign(doc.fullPath() + hash); | ||
| 110 | } | 100 | } |
| 101 | const previousDoc = this.doc; | ||
| 102 | this.doc = null; | ||
| 111 | 103 | ||
| 112 | reset() { | 104 | this.tag.textContent = ""; |
| 113 | if (!this.doc) { | 105 | this.tag.style.display = "none"; |
| 114 | return; | ||
| 115 | } | ||
| 116 | const previousDoc = this.doc; | ||
| 117 | this.doc = null; | ||
| 118 | 106 | ||
| 119 | this.tag.textContent = ""; | 107 | this.input.setAttribute("placeholder", this.placeholder); |
| 120 | this.tag.style.display = "none"; | 108 | this.input.style.paddingLeft = ""; |
| 121 | 109 | ||
| 122 | this.input.setAttribute("placeholder", this.placeholder); | 110 | this.trigger("change", null, previousDoc); |
| 123 | this.input.style.paddingLeft = ""; | 111 | } |
| 124 | 112 | ||
| 125 | this.trigger("change", null, previousDoc); | 113 | doScopeSearch(event) { |
| 114 | this.search(this.input.value.slice(0, this.input.selectionStart)); | ||
| 115 | if (this.doc) { | ||
| 116 | $.stopEvent(event); | ||
| 126 | } | 117 | } |
| 118 | } | ||
| 127 | 119 | ||
| 128 | doScopeSearch(event) { | 120 | onClick(event) { |
| 129 | this.search(this.input.value.slice(0, this.input.selectionStart)); | 121 | if (event.target === this.tag) { |
| 130 | if (this.doc) { | 122 | this.reset(); |
| 131 | $.stopEvent(event); | 123 | $.stopEvent(event); |
| 132 | } | ||
| 133 | } | 124 | } |
| 125 | } | ||
| 134 | 126 | ||
| 135 | onClick(event) { | 127 | onKeydown(event) { |
| 136 | if (event.target === this.tag) { | 128 | if (event.which === 8) { |
| 129 | // backspace | ||
| 130 | if (this.doc && this.input.selectionEnd === 0) { | ||
| 137 | this.reset(); | 131 | this.reset(); |
| 138 | $.stopEvent(event); | 132 | $.stopEvent(event); |
| 139 | } | 133 | } |
| 140 | } | 134 | } else if (!this.doc && this.input.value && !$.isChromeForAndroid()) { |
| 141 | 135 | if (event.ctrlKey || event.metaKey || event.altKey || event.shiftKey) { | |
| 142 | onKeydown(event) { | ||
| 143 | if (event.which === 8) { | ||
| 144 | // backspace | ||
| 145 | if (this.doc && this.input.selectionEnd === 0) { | ||
| 146 | this.reset(); | ||
| 147 | $.stopEvent(event); | ||
| 148 | } | ||
| 149 | } else if (!this.doc && this.input.value && !$.isChromeForAndroid()) { | ||
| 150 | if (event.ctrlKey || event.metaKey || event.altKey || event.shiftKey) { | ||
| 151 | return; | ||
| 152 | } | ||
| 153 | if ( | ||
| 154 | event.which === 9 || // tab | ||
| 155 | (event.which === 32 && app.isMobile()) | ||
| 156 | ) { | ||
| 157 | // space | ||
| 158 | this.doScopeSearch(event); | ||
| 159 | } | ||
| 160 | } | ||
| 161 | } | ||
| 162 | |||
| 163 | onTextInput(event) { | ||
| 164 | if (!$.isChromeForAndroid()) { | ||
| 165 | return; | 136 | return; |
| 166 | } | 137 | } |
| 167 | if (!this.doc && this.input.value && event.data === " ") { | 138 | if ( |
| 139 | event.which === 9 || // tab | ||
| 140 | (event.which === 32 && app.isMobile()) | ||
| 141 | ) { | ||
| 142 | // space | ||
| 168 | this.doScopeSearch(event); | 143 | this.doScopeSearch(event); |
| 169 | } | 144 | } |
| 170 | } | 145 | } |
| 146 | } | ||
| 171 | 147 | ||
| 172 | extractHashValue() { | 148 | onTextInput(event) { |
| 173 | let value; | 149 | if (!$.isChromeForAndroid()) { |
| 174 | if ((value = this.getHashValue())) { | 150 | return; |
| 175 | const newHash = $.urlDecode(location.hash).replace( | ||
| 176 | `#${SEARCH_PARAM}=${value} `, | ||
| 177 | `#${SEARCH_PARAM}=`, | ||
| 178 | ); | ||
| 179 | app.router.replaceHash(newHash); | ||
| 180 | return value; | ||
| 181 | } | ||
| 182 | } | 151 | } |
| 152 | if (!this.doc && this.input.value && event.data === " ") { | ||
| 153 | this.doScopeSearch(event); | ||
| 154 | } | ||
| 155 | } | ||
| 183 | 156 | ||
| 184 | getHashValue() { | 157 | extractHashValue() { |
| 185 | try { | 158 | let value; |
| 186 | return __guard__( | 159 | if ((value = this.getHashValue())) { |
| 187 | HASH_RGX.exec($.urlDecode(location.hash)), | 160 | const newHash = $.urlDecode(location.hash).replace( |
| 188 | (x) => x[1], | 161 | `#${SearchScope.SEARCH_PARAM}=${value} `, |
| 189 | ); | 162 | `#${SearchScope.SEARCH_PARAM}=`, |
| 190 | } catch (error) {} | 163 | ); |
| 164 | app.router.replaceHash(newHash); | ||
| 165 | return value; | ||
| 191 | } | 166 | } |
| 167 | } | ||
| 192 | 168 | ||
| 193 | afterRoute(name, context) { | 169 | getHashValue() { |
| 194 | if (!app.isSingleDoc() && context.init && context.doc) { | 170 | try { |
| 195 | this.selectDoc(context.doc); | 171 | return SearchScope.HASH_RGX.exec($.urlDecode(location.hash))?.[1]; |
| 196 | } | 172 | } catch (error) {} |
| 173 | } | ||
| 174 | |||
| 175 | afterRoute(name, context) { | ||
| 176 | if (!app.isSingleDoc() && context.init && context.doc) { | ||
| 177 | this.selectDoc(context.doc); | ||
| 197 | } | 178 | } |
| 198 | }; | 179 | } |
| 199 | app.views.SearchScope.initClass(); | 180 | }; |
| 200 | return app.views.SearchScope; | ||
| 201 | })(); | ||
| 202 | |||
| 203 | function __guard__(value, transform) { | ||
| 204 | return typeof value !== "undefined" && value !== null | ||
| 205 | ? transform(value) | ||
| 206 | : undefined; | ||
| 207 | } | ||