SmartbarInputUtils.mjs (2405B)
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 import { MultilineEditor } from "chrome://browser/content/multilineeditor/multiline-editor.mjs"; 6 7 /** 8 * Creates a Smartbar editor element. 9 * 10 * @param {HTMLInputElement | MultilineEditor} inputElement 11 * The input element to replace. 12 * @returns {{ 13 * input: MultilineEditor, 14 * editor: object 15 * } | null} 16 * An object with the new editor element and the adapter. 17 */ 18 export function createEditor(inputElement) { 19 if (!inputElement) { 20 return null; 21 } 22 23 if (inputElement instanceof MultilineEditor) { 24 return { 25 input: inputElement, 26 editor: createEditorAdapter(inputElement), 27 }; 28 } 29 30 const doc = inputElement.ownerDocument; 31 const editorElement = /** @type {MultilineEditor} */ ( 32 doc.createElement("moz-multiline-editor") 33 ); 34 35 // Copy attributes except those that don’t apply. 36 for (const attr of inputElement.attributes) { 37 if (attr.name == "type" || attr.name == "value") { 38 continue; 39 } 40 editorElement.setAttribute(attr.name, attr.value); 41 } 42 43 editorElement.className = inputElement.className; 44 editorElement.id = inputElement.id; 45 editorElement.value = inputElement.value ?? ""; 46 47 inputElement.replaceWith(editorElement); 48 return { 49 input: editorElement, 50 editor: createEditorAdapter(editorElement), 51 }; 52 } 53 54 /** 55 * Creates an adapter for the Smartbar editor element. 56 * 57 * @param {MultilineEditor} editorElement 58 * The editor element. 59 */ 60 export function createEditorAdapter(editorElement) { 61 const getSelectionBounds = () => { 62 let start = editorElement.selectionStart ?? 0; 63 let end = editorElement.selectionEnd ?? start; 64 if (start > end) { 65 [start, end] = [end, start]; 66 } 67 return { start, end }; 68 }; 69 70 return { 71 get composing() { 72 return !!editorElement.composing; 73 }, 74 selection: { 75 get rangeCount() { 76 const { start, end } = getSelectionBounds(); 77 return start === end && editorElement.value === "" ? 0 : 1; 78 }, 79 toStringWithFormat() { 80 const { start, end } = getSelectionBounds(); 81 if (start == null || end == null) { 82 return ""; 83 } 84 return editorElement.value?.substring(start, end); 85 }, 86 }, 87 }; 88 }