如何在 react / textarea 中替换 'selected text' => 'decorated text'?我无法获得 'selected text' 的确切位置(索引)
how to replace 'selected text' => 'decorated text' in react / textarea? i can't get exact location(index) of 'selected text'
我正在尝试用 React 构建一些文本编辑器
我的母语不是英语,很抱歉回答下面的问题
我想做的是下面这样
(it's 'notion' page gif)
- 如果用户用鼠标(或键盘)拖动文本在某些文本中设置块,
- 弹出菜单(编辑'seleted texts')显示
我被第一个卡住了。
我可以得到整个文本和选定的文本
let wholeText = whole.anchorNode.childNodes[0].defaultValue;
let selectedText = window.getSelection().toString();
但我无法在 wholeText
中获得 selectedText
的 'exact location'
这是我的代码(反应,样式组件)
import { useState, useEffect } from 'react';
import styled from 'styled-components';
import autosize from 'autosize';
export default function TextBox({ id, index, content, handleContentInput }) {
const [currentContent, setCurrentContent] = useState(content);
const [areaHeight, setAreaHeight] = useState(25);
useEffect(() => {
autosize(document.querySelector(`.TextBoxWrap_${id}`));
}, [currentContent]);
return (
<TextBoxContainer
className={`TextBoxContainer_${id}`}
areaHeight={areaHeight}
onClick={() => {
document.querySelector(`.TextBoxContainer_${id}`).focus();
}}
>
<TextBoxWrap
className={`TextBoxWrap_${id}`}
areaHeight={areaHeight}
onChange={(event) => {
setCurrentContent(event.target.value);
}}
onBlur={() => handleContentInput(id, index, currentContent)}
onKeyUp={() => {
let newHeight = document.querySelector(`.TextBoxWrap_${id}`)
.clientHeight;
setAreaHeight(newHeight);
}}
onMouseUp={() => {
let whole = window.getSelection();
if (!whole) return;
let range = whole.getRangeAt(0);
console.log({ whole, range });
let wholeText = whole.anchorNode.childNodes[0].defaultValue;
let selectedText = whole.toString();
console.log({ wholeText, selectedText });
let start = range.startOffset; // Start position
let end = range.endOffset; // End position
console.log({ start, end });
}}
value={currentContent}
></TextBoxWrap>
</TextBoxContainer>
);
}
const TextBoxContainer = styled.div`
max-width: 890px;
width: 100%;
height: ${(props) => `${props.areaHeight}px`};
border: 1px solid black;
margin: 3px;
padding: 2px;
`;
const TextBoxWrap = styled.textarea`
/* border: 1px solid black; */
box-sizing: 'border-box';
border: none;
outline: none;
width: 100%;
min-height: 20px;
height: 20px;
/* padding: 2x; */
box-shadow: none;
display: block;
overflow: hidden; // Removes scrollbar
resize: none;
font-size: 18px;
/* line-height: 1.5em; */
/* font-family: Georgia, 'Malgun Gothic', serif; */
`;
在onMouseUp
里面,它是这样工作的
- console.log({ wholeText, selectedText }); : 工作正常
- console.log({开始,结束}); : 总是 0, 0
wholeText.indexOf(selectedText)
是我的选择,但 indexOf()
只给我 'first' 索引匹配,
所以,即使我想要“aaaaaa'a'aa”,但 indexOf 会给我“0”(=>“'a'aaaaaaaaaa”)
我在想什么,
- 得到'exact index(location)',用它剪
wholeText
- 用弹出框装饰
selectedText
(return html元素?喜欢${selectedText}
- 然后,合并这三项(wholeText_front、decorated_selectedText、wholeText_back)
- 并且,将弹出菜单 div 放在所选文本的正上方
这意味着,我需要'选择一个人的位置
我该怎么做?请给我建议
谢谢!
post我之前看过post这个问题
我可能对我的问题有一些解决方案,所以 post 我自己回答这个问题
在这个问题(How to get the start and end points of selection in text area?)中,'Tim Down'用getInputSelection
函数回答。
getInputSelection
需要 el
作为参数,我认为这是某种 'html element'
所以,根据这个问题(使用 javascript 获取焦点元素的 ID
),我得到了一个提示:document.activeElement
而且,我尝试了 getInputSelection(document.activeElement)
并得到了一个像 { start: (number), end: (number) }
这样的对象
我正在尝试用 React 构建一些文本编辑器
我的母语不是英语,很抱歉回答下面的问题
我想做的是下面这样
(it's 'notion' page gif)
- 如果用户用鼠标(或键盘)拖动文本在某些文本中设置块,
- 弹出菜单(编辑'seleted texts')显示
我被第一个卡住了。
我可以得到整个文本和选定的文本
let wholeText = whole.anchorNode.childNodes[0].defaultValue;
let selectedText = window.getSelection().toString();
但我无法在 wholeText
selectedText
的 'exact location'
这是我的代码(反应,样式组件)
import { useState, useEffect } from 'react';
import styled from 'styled-components';
import autosize from 'autosize';
export default function TextBox({ id, index, content, handleContentInput }) {
const [currentContent, setCurrentContent] = useState(content);
const [areaHeight, setAreaHeight] = useState(25);
useEffect(() => {
autosize(document.querySelector(`.TextBoxWrap_${id}`));
}, [currentContent]);
return (
<TextBoxContainer
className={`TextBoxContainer_${id}`}
areaHeight={areaHeight}
onClick={() => {
document.querySelector(`.TextBoxContainer_${id}`).focus();
}}
>
<TextBoxWrap
className={`TextBoxWrap_${id}`}
areaHeight={areaHeight}
onChange={(event) => {
setCurrentContent(event.target.value);
}}
onBlur={() => handleContentInput(id, index, currentContent)}
onKeyUp={() => {
let newHeight = document.querySelector(`.TextBoxWrap_${id}`)
.clientHeight;
setAreaHeight(newHeight);
}}
onMouseUp={() => {
let whole = window.getSelection();
if (!whole) return;
let range = whole.getRangeAt(0);
console.log({ whole, range });
let wholeText = whole.anchorNode.childNodes[0].defaultValue;
let selectedText = whole.toString();
console.log({ wholeText, selectedText });
let start = range.startOffset; // Start position
let end = range.endOffset; // End position
console.log({ start, end });
}}
value={currentContent}
></TextBoxWrap>
</TextBoxContainer>
);
}
const TextBoxContainer = styled.div`
max-width: 890px;
width: 100%;
height: ${(props) => `${props.areaHeight}px`};
border: 1px solid black;
margin: 3px;
padding: 2px;
`;
const TextBoxWrap = styled.textarea`
/* border: 1px solid black; */
box-sizing: 'border-box';
border: none;
outline: none;
width: 100%;
min-height: 20px;
height: 20px;
/* padding: 2x; */
box-shadow: none;
display: block;
overflow: hidden; // Removes scrollbar
resize: none;
font-size: 18px;
/* line-height: 1.5em; */
/* font-family: Georgia, 'Malgun Gothic', serif; */
`;
在onMouseUp
里面,它是这样工作的
- console.log({ wholeText, selectedText }); : 工作正常
- console.log({开始,结束}); : 总是 0, 0
wholeText.indexOf(selectedText)
是我的选择,但 indexOf()
只给我 'first' 索引匹配,
所以,即使我想要“aaaaaa'a'aa”,但 indexOf 会给我“0”(=>“'a'aaaaaaaaaa”)
我在想什么,
- 得到'exact index(location)',用它剪
wholeText
- 用弹出框装饰
selectedText
(return html元素?喜欢${selectedText} - 然后,合并这三项(wholeText_front、decorated_selectedText、wholeText_back)
- 并且,将弹出菜单 div 放在所选文本的正上方
这意味着,我需要'选择一个人的位置
我该怎么做?请给我建议
谢谢!
post我之前看过post这个问题
我可能对我的问题有一些解决方案,所以 post 我自己回答这个问题
在这个问题(How to get the start and end points of selection in text area?)中,'Tim Down'用getInputSelection
函数回答。
getInputSelection
需要 el
作为参数,我认为这是某种 'html element'
所以,根据这个问题(使用 javascript 获取焦点元素的 ID
),我得到了一个提示:document.activeElement
而且,我尝试了 getInputSelection(document.activeElement)
并得到了一个像 { start: (number), end: (number) }