检查用户是否在两个字符之间键入 textarea

check if user is typing between two characters textarea

提问人:Waseem Munir 提问时间:11/14/2023 最后编辑:Waseem Munir 更新时间:11/20/2023 访问量:109

问:

我有一个文本区域,默认情况下将包含任何类型的字符串,并且用户无法键入,除非他在左括号和右括号内键入,例如“Leave[]”我可以在括号内键入,但不能在括号外也可以嵌套,直到 n 级,例如 Leave[ Nested[ Test[] ],我想要一个函数来检查用户是否在括号内键入以返回否则truefalse

const checkIfTypingBetweenBrackets=(prev:string,current:string):boolean =>{

// Code goes here

}


JavaScript ReactJS 字符串 递归

评论

0赞 James Hibbard 11/14/2023
只是为了检查我的理解,每当 textarea 接收到输入时,您都要检查它是否正确嵌套在方括号之间。因此,“Leave[Test[Again[Nested[]]]”是可以的,但例如“Leave[Test[Again[Nested[]foor]]”或“Leave[Test[Again[Nested[]]bar]”就不行了。
0赞 Waseem Munir 11/14/2023
不,我们必须检查用户是否在括号之间键入,因此将有一个默认文本,例如 Leave[Test[Nested[]]] 现在我只能在括号之间键入,而不能在括号之外键入,Leave[Test(我也可以在这里键入,因为它在括号中)[嵌套[这是我键入的]]] 看到我在括号内键入。但是我不能这样做“离开[嵌套[]]我不能在这里或之前输入”
1赞 Kaiido 11/14/2023
他们可以输入和删除这样的括号吗?因此,假设原始输入是用户将其编辑为,这似乎是您的规则所允许的,然后再次将其编辑为,即它们只是在 之后插入。他们现在可以编辑零件吗?请注意,文本编辑(非常)困难,有很多边缘情况需要处理。foo[]foo[bar bla]foo[bar] bla]]blabla]
0赞 James Hibbard 11/14/2023
那么在开始和结束括号之间有任何内容是允许的吗?即“Leave[Nested[this is fine]]”、“Leave[Nested[]so is this]”、“Leave[this too Nested[]]”。我说对了吗?如果您编辑问题以扩展您的要求,可能会有所帮助。@Kaiido也提出了一个好观点。在这种情况下会发生什么?
0赞 Waseem Munir 11/14/2023
是的,你是对的,我们可以在左括号和右括号之间进行编辑,例如 foo[bar] bla], foo[bar]]]] bla] 它有一个左括号和右括号,不管我们输入什么,我只需要一个函数,如果用户在左括号和右括号之间键入,则返回布尔值,但它应该像“foo[”我一样小心,然后, 该函数将返回 false

答:

-2赞 Akeel Ahmed Qureshi 11/14/2023 #1

输入状态使用方括号进行初始化。checkTyping 函数检查光标是否在方括号内,如果光标在方括号内,则忽略输入。

import React, { useState, useRef } from 'react';

const BracketText = () => {
  const [input, setInput] = useState('[]');
  const textareaRef = useRef(null);

  const checkTyping = (text) => {
    const { selectionStart, selectionEnd } = textareaRef.current;
    return selectionStart > 0 && selectionEnd <= text.length - 1;
  };

  const handleChange = (e) => {
    const currentValue = e.target.value;

    if (checkTyping(currentValue)) {
      setInput(currentValue);
    }
  };

  return (
    <div>
      <textarea
        ref={textareaRef}
        value={input}
        onChange={handleChange}
      />
    </div>
  );
};

export default BracketText;

评论

0赞 Akeel Ahmed Qureshi 11/20/2023
我已经更新了代码,也许对你有帮助。
1赞 Kaiido 11/14/2023 #2

如果我正确理解了这些要求,那么可以有嵌套括号的事实并不重要。重要的是最外层括号内的内容。

因此,我们能做的是在接收输入之前检查当前和位置,并将其与 a 的第一个索引和 a 的最后一个索引进行比较。
您还需要特别注意一些输入,例如退格键或前向删除,以便它们不会破坏最外层的括号:
selectionStartselectionEnd<textarea>[]

const textarea = document.querySelector("textarea");
textarea.onbeforeinput = (evt) => {
  const { selectionStart, selectionEnd, value } = textarea;
  const bracketStart = value.indexOf("[");
  const bracketEnd   = value.lastIndexOf("]");

  if (selectionStart <= bracketStart || selectionEnd > bracketEnd) {
    evt.preventDefault();
  }
  if (evt.inputType === "deleteContentBackward" && selectionEnd === bracketStart + 1) {
    evt.preventDefault();
  }
  if (evt.inputType === "deleteContentForward" && selectionStart === bracketEnd) {
    evt.preventDefault();
  }
  // If you want to handle these ones, you'd need to measure the closest word and check if it's attached to your brackets.
  if (evt.inputType === "deleteWordBackward" || evt.inputType === "deleteWordForward") {
    evt.preventDefault();
  }
}
<textarea>Leave[]</textarea>

注意:我没有对此进行广泛的测试,文本编辑是一个非常复杂的问题,因此可能有一些边缘情况是这个代码段无法处理的。

评论

0赞 James Hibbard 11/14/2023
这是我最初的想法,但似乎这里比检查最外层括号之间的内容更重要(参见 OP 的评论)。
0赞 Kaiido 11/14/2023
@JamesHibbard好吧......我不能 100% 确定这是他们所追求的,(此外,由于他们并没有真正响应,我希望向他们展示解决方案将有助于他们定义他们的问题),但从我所读到的内容来看,他们仍然处于“防止在括号外写作”的步骤。这个答案解决了这个问题。下一步是在调用 API 之前解析所有括号。但那将是另一个问题,这两个问题只是切线相关的。
0赞 James Hibbard 11/14/2023
绝对。FWIW,你的答案很好。我从中学到了一两个技巧。
0赞 Waseem Munir 11/14/2023
@Kaiido根据您的回答和评论,我把它弄出来了,我正在使用 ReactJS,所以那里会有所不同,我正在添加答案,所以如果有人需要,非常感谢
0赞 Waseem Munir 11/14/2023 #3

正如@Kaiido提到的,我不必担心嵌套括号,只需要关注最外层的括号,所以基于他的解决方案

随心所欲地编写以下函数

const checkIfTypingBetweenBrackets = (previousText, currentText) => {
  let prevBracketOpen = previousText.indexOf("[");
  let prevBracketClose = previousText.lastIndexOf("]");
  let currentBracketOpen = currentText.indexOf("[");
  let currentBracketClose = currentText.lastIndexOf("]");

  if (
    currentBracketClose - currentBracketOpen >
    prevBracketClose - prevBracketOpen
  ) {
    return true;
  } else {
    return false;
  }
};

现在在将值保存为状态之前在 onChange 上使用它

  <textarea
      value={value}
      onChange={(e) => {
        // Here value argument is the previous value as we have not stored the latest value in state, and e.target.value is the latest value
        let ifBetweenBrackets = checkIfTypingBetweenBrackets(
          value,
          e.target.value
        );
        // Only update the value in state if user is typing between brackets
        if (ifBetweenBrackets) {
          setValue(e.target.value);
        }
      }}
    />