Open ianTevesAcc opened 4 months ago
I tried to fix my own problem and came up with the following.
(child) => child instanceof HTMLTextAreaElement ? true : null,
(child) => child instanceof HTMLInputElement && (child.type === "text" || child.type === "search") ? true : null
or
(child: HTMLElement): boolean | null => child instanceof HTMLTextAreaElement ? true : null,
(child: HTMLElement): boolean | null => child instanceof HTMLInputElement && (child.getAttribute("type") === "text" || child.getAttribute("type") === "search") ? true : null
Problem is the textarea / input element is not being selected. I tried applying some more code other than this (more logic in order to handle key presses and etc.) but it didn't end fruitful for me. Do you know how to solve this problem?
FIXED IT!!!
Added the following...
if (this.elementsWithUniqueStrings.has(inputString)) {
let elementToClick = this.elementsWithUniqueStrings.get(inputString);
if (elementToClick instanceof SVGSVGElement && elementToClick.parentElement) {
elementToClick = elementToClick.parentElement;
}
this.removeOverlay();
if (isTickPressed) {
elementToClick?.dispatchEvent(new MouseEvent("contextmenu", { bubbles: true, clientX: elementToClick.getBoundingClientRect().left + elementToClick.clientWidth / 2, clientY: elementToClick.getBoundingClientRect().top + elementToClick.clientHeight / 2 }));
} else {
// Find the textarea child element within the div container
const textareaElement = elementToClick?.querySelector('textarea');
if (textareaElement) {
textareaElement.dispatchEvent(new MouseEvent("click", { bubbles: true }));
// Focus on textarea element after click
if (document && document.activeElement !== textareaElement) {
document.activeElement?.blur();
}
setTimeout(() => {
textareaElement?.focus();
}, 0);
}
}
isTickPressed = false;
}
or
if (this.elementsWithUniqueStrings.has(inputString)) {
let elementToClick = this.elementsWithUniqueStrings.get(inputString);
if (elementToClick instanceof SVGSVGElement && elementToClick.parentElement) {
elementToClick = elementToClick.parentElement;
}
this.removeOverlay();
if (isTickPressed) {
elementToClick?.dispatchEvent(new MouseEvent("contextmenu", { bubbles: true, clientX: elementToClick.getBoundingClientRect().left + elementToClick.clientWidth / 2, clientY: elementToClick.getBoundingClientRect().top + elementToClick.clientHeight / 2 }));
} else {
// Find the textarea child element within the div container
const textareaElement = elementToClick?.querySelector('textarea');
if (textareaElement) {
textareaElement.dispatchEvent(new MouseEvent("click", { bubbles: true }));
// Focus on textarea element after click
if (document && document.activeElement !== textareaElement) {
document.activeElement?.blur();
}
setTimeout(() => {
textareaElement?.focus();
}, 0);
}
}
isTickPressed = false;
}
To be more specific...
attachStringsToElements() {
const rules = [
// ADDED CODE -------------------------------------------------------------------------- //
(child) => child instanceof HTMLTextAreaElement ? true : null,
(child) => child instanceof HTMLInputElement && (child.type === "text" || child.type === "search") ? true : null,
// ---------------------------------------------------------------------------------------//
(child) => {
var _a, _b;
return child instanceof SVGSVGElement && !((_a = child.classList) == null ? void 0 : _a.contains("canvas-background")) && !((_b = child.classList) == null ? void 0 : _b.contains("canvas-edges")) ? true : null;
},
(child) => child instanceof HTMLInputElement && child.type === "checkbox" ? true : null,
(child) => {
var _a;
return ((_a = child.classList) == null ? void 0 : _a.contains("canvas-node-label")) ? false : null;
},
(child) => {
var _a;
return ((_a = child.classList) == null ? void 0 : _a.contains("canvas-node-container")) ? true : null;
}
];
const processQueue = (queue) => {
var _a, _b;
if (!queue.length)
return;
const element = queue.shift();
if (!element) {
processQueue(queue);
return;
}
const pushChildren = (child) => {
var _a2;
if (child instanceof Element) {
const style = window.getComputedStyle(child);
if (style.display === "none") {
return false;
}
}
queue.push(child);
for (const rule of rules) {
const result = rule(child);
if (result !== null) {
return result;
}
}
return !!(child.nodeType === Node.TEXT_NODE && ((_a2 = child.textContent) == null ? void 0 : _a2.trim()) && child.textContent !== "/");
};
const hasSvgOrTextContentChild = (Array.from(element.childNodes).some(pushChildren) || ((_a = element.classList) == null ? void 0 : _a.contains("canvas-color-picker-item")) || element instanceof HTMLInputElement && element.type === "search" || element instanceof HTMLSelectElement) && !((_b = element == null ? void 0 : element.classList) == null ? void 0 : _b.contains("canvas-icon-placeholder"));
if (hasSvgOrTextContentChild) {
const style = window.getComputedStyle(element);
if (style.display !== "none" && this.isElementInViewport(element)) {
const elementPosition = element.getBoundingClientRect();
if (elementPosition.top !== 0 || elementPosition.left !== 0) {
const uniqueString = this.uniqueStrings.generateUniqueString();
this.elementsWithUniqueStrings.set(uniqueString, element);
const stringElement = this.overlay.createEl("span", {
cls: "surfing-key-string",
attr: {
id: uniqueString
}
});
stringElement.textContent = uniqueString;
const midPointX = elementPosition.left + elementPosition.width / 2;
const midPointY = elementPosition.top + elementPosition.height / 2;
const stringElementRect = stringElement.getBoundingClientRect();
const overlayRect = this.overlay.getBoundingClientRect();
const stringWidth = stringElementRect.width;
const stringHeight = stringElementRect.height;
const rightPosition = midPointX + stringWidth / 2;
const bottomPosition = midPointY + stringHeight / 2;
if (rightPosition > overlayRect.right) {
stringElement.style.left = `${midPointX - stringWidth}px`;
} else {
stringElement.style.left = `${midPointX}px`;
}
if (bottomPosition > overlayRect.bottom) {
stringElement.style.top = `${midPointY - stringHeight}px`;
} else if (midPointY + stringHeight / 2 > overlayRect.bottom) {
stringElement.style.top = `${midPointY - stringHeight}px`;
} else {
stringElement.style.top = `${midPointY - 2}px`;
}
}
}
}
processQueue(queue);
};
processQueue([this.doc instanceof Document ? this.doc.documentElement : this.doc]);
}
monitorUserInput() {
const inputQueue = [];
let isTickPressed = false;
this.keydownHandler = (e) => {
var _a, _b;
if (!this.overlay)
return;
e.stopPropagation();
e.preventDefault();
if (e.key === "Escape") {
this.removeOverlay();
return;
}
if (import_obsidian.Keymap.isModifier(e, "Mod") || import_obsidian.Keymap.isModifier(e, "Shift") || import_obsidian.Keymap.isModifier(e, "Alt")) {
return;
}
if (e.key === "`") {
isTickPressed = true;
return;
}
if (!/^[qwertasdfgzxcvbQWERTASDFGZXCVB]$/i.test(e.key)) {
if (e.key === "Backspace" || e.key === "Delete") {
inputQueue.pop();
isTickPressed = false;
const inputDisplay2 = this.overlay.querySelector("#inputDisplay");
if (inputDisplay2) {
inputDisplay2.textContent = inputQueue.join("");
}
for (const [uniqueString, _] of this.elementsWithUniqueStrings.entries()) {
const stringElement = document.getElementById(uniqueString);
stringElement == null ? void 0 : stringElement.show();
}
}
return;
}
const input = e.key.toUpperCase();
if (inputQueue.length >= 2 && this.uniqueStrings.usedChars.has(inputQueue.join("")[0])) {
inputQueue.shift();
} else if (inputQueue.length >= 3) {
inputQueue.shift();
}
inputQueue.push(input);
const inputDisplay = this.overlay.querySelector("#inputDisplay");
if (inputDisplay) {
inputDisplay.textContent = inputQueue.join("");
}
const inputString = inputQueue.join("");
for (const [uniqueString, _] of this.elementsWithUniqueStrings.entries()) {
const stringElement = document.getElementById(uniqueString);
if (stringElement && ((_a = stringElement.textContent) == null ? void 0 : _a.startsWith(inputString))) {
stringElement.style.backgroundColor = "yellow";
stringElement.style.color = "black";
} else {
stringElement == null ? void 0 : stringElement.hide();
}
}
if (this.elementsWithUniqueStrings.has(inputString)) {
let elementToClick = this.elementsWithUniqueStrings.get(inputString);
if (elementToClick instanceof SVGSVGElement && elementToClick.parentElement) {
elementToClick = elementToClick.parentElement;
}
this.removeOverlay();
if (isTickPressed) {
elementToClick == null ? void 0 : elementToClick.dispatchEvent(new MouseEvent("contextmenu", { bubbles: true, clientX: elementToClick.getBoundingClientRect().left + elementToClick.clientWidth / 2, clientY: elementToClick.getBoundingClientRect().top + elementToClick.clientHeight / 2 }));
} else {
elementToClick == null ? void 0 : elementToClick.dispatchEvent(new MouseEvent("click", { bubbles: true }));
if (elementToClick instanceof HTMLInputElement) {
if (document && document.activeElement !== elementToClick) {
(_b = document.activeElement) == null ? void 0 : _b.blur();
}
setTimeout(() => {
elementToClick == null ? void 0 : elementToClick.focus();
}, 0);
}
}
isTickPressed = false;
}
// ADDED CODE -------------------------------------------------------- //
if (this.elementsWithUniqueStrings.has(inputString)) {
let elementToClick = this.elementsWithUniqueStrings.get(inputString);
if (elementToClick instanceof SVGSVGElement && elementToClick.parentElement) {
elementToClick = elementToClick.parentElement;
}
this.removeOverlay();
if (isTickPressed) {
elementToClick?.dispatchEvent(new MouseEvent("contextmenu", { bubbles: true, clientX: elementToClick.getBoundingClientRect().left + elementToClick.clientWidth / 2, clientY: elementToClick.getBoundingClientRect().top + elementToClick.clientHeight / 2 }));
} else {
// Find the textarea child element within the div container
const textareaElement = elementToClick?.querySelector('textarea');
if (textareaElement) {
textareaElement.dispatchEvent(new MouseEvent("click", { bubbles: true }));
// Focus on textarea element after click
if (document && document.activeElement !== textareaElement) {
document.activeElement?.blur();
}
setTimeout(() => {
textareaElement?.focus();
}, 0);
}
}
isTickPressed = false;
}
// -----------------------------------------------------------------------------------//
};
window.addEventListener("keydown", this.keydownHandler, true);
}
Feature Requested
Just like the title I want to be able to select textarea elements inside obsidian.
Use Case: For people who use plugins that require to select a textarea element in order to type text into. An example is that I use Obsidian Copilot and I regularly select the textarea element of my copilot plugin in order to gpt questions.
Current work around is the mouse. But using the mouse is for the weak only.
Relevant Screenshot
No response
Checklist