SmartbarInputController.mjs (4073B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 /** 6 * @import {MultilineEditor} from "chrome://browser/content/multilineeditor/multiline-editor.mjs" 7 */ 8 9 /** 10 * Controller for the Smartbar editor. 11 * 12 * The controller abstracts the underlying editor implementation allowing 13 * the Smartbar to also work with a standard HTML input. 14 */ 15 export class SmartbarInputController { 16 /** 17 * @param {object} adapter 18 * Adapter with input and editor references. 19 * @param {MultilineEditor | HTMLInputElement} adapter.input 20 * The input element. 21 * @param {object} adapter.editor 22 * The editor object. 23 */ 24 constructor(adapter) { 25 /** @type {MultilineEditor | HTMLInputElement} */ 26 this.input = adapter.input; 27 /** @type {object} */ 28 this.editor = adapter.editor; 29 } 30 31 /** 32 * Focuses the input element. 33 */ 34 focus() { 35 this.input.focus(); 36 } 37 38 /** 39 * Removes focus from the input element. 40 */ 41 blur() { 42 this.input.blur(); 43 } 44 45 /** 46 * Whether the input is read-only. 47 * 48 * @type {boolean} 49 */ 50 get readOnly() { 51 return this.input.readOnly; 52 } 53 54 set readOnly(val) { 55 this.input.readOnly = val; 56 } 57 58 /** 59 * The placeholder text for the input. 60 * 61 * @type {string} 62 */ 63 get placeholder() { 64 return this.input.placeholder ?? ""; 65 } 66 67 set placeholder(val) { 68 this.input.placeholder = val ?? ""; 69 } 70 71 /** 72 * The current value of the input. 73 * 74 * @type {string} 75 */ 76 get value() { 77 return this.input.value ?? ""; 78 } 79 80 /** 81 * Sets the value of the input. 82 * 83 * @param {string} val 84 */ 85 setValue(val) { 86 this.input.value = val ?? ""; 87 } 88 89 /** 90 * The start offset of the selection. 91 * 92 * @type {number} 93 */ 94 get selectionStart() { 95 return this.input.selectionStart ?? 0; 96 } 97 98 set selectionStart(val) { 99 this.setSelectionRange(val, this.selectionEnd ?? val); 100 } 101 102 /** 103 * The end offset of the selection. 104 * 105 * @type {number} 106 */ 107 get selectionEnd() { 108 return this.input.selectionEnd ?? 0; 109 } 110 111 set selectionEnd(val) { 112 this.setSelectionRange(this.selectionStart ?? 0, val); 113 } 114 115 /** 116 * Sets the selection range in the input. 117 * 118 * @param {number} start 119 * The start offset. 120 * @param {number} end 121 * The end offset. 122 */ 123 setSelectionRange(start, end) { 124 if (!this.input.setSelectionRange) { 125 return; 126 } 127 const from = Math.max(0, start ?? 0); 128 const to = Math.max(from, end ?? from); 129 this.input.setSelectionRange(from, to); 130 } 131 132 /** 133 * Selects all text in the input. 134 */ 135 select() { 136 this.input.select?.(); 137 } 138 139 /** 140 * Dispatches an input event on the input element. 141 * 142 * @param {object} [options] 143 * The event options. 144 * @param {string} [options.inputType="insertText"] 145 * The input type. 146 * @param {string} [options.data=""] 147 * The data being inserted. 148 */ 149 dispatchInput({ inputType = "insertText", data = "" } = {}) { 150 this.input.dispatchEvent( 151 new InputEvent("input", { 152 bubbles: true, 153 composed: true, 154 inputType, 155 data, 156 }) 157 ); 158 } 159 160 /** 161 * Dispatches a selectionchange event on the input element. 162 */ 163 dispatchSelectionChange() { 164 this.input.dispatchEvent( 165 new Event("selectionchange", { bubbles: true, composed: true }) 166 ); 167 } 168 169 /** 170 * Whether the editor is in composition mode. 171 * 172 * @type {boolean} 173 */ 174 get composing() { 175 return this.editor.composing ?? false; 176 } 177 178 /** 179 * The number of selection ranges in the editor. 180 * 181 * @type {number} 182 */ 183 get selectionRangeCount() { 184 return this.editor.selection?.rangeCount ?? 0; 185 } 186 187 /** 188 * Returns the string representation of the current selection with formatting. 189 * 190 * @returns {string} 191 * The formatted selection string. 192 */ 193 selectionToStringWithFormat() { 194 return this.editor.selection?.toStringWithFormat() ?? ""; 195 } 196 }