Home > Net >  Send keystrokes to a specific text input if not captured by any other input
Send keystrokes to a specific text input if not captured by any other input

Time:09-29

I'm trying to emulate the behavior of apps like Discord, where you can type into the message box even if it isn't focused. I'd like to do this only if no other input on the page is focused.

I tried immediately focusing the MessageBox input on blur, but this traps focus in MessageBox doesn't let me type into any other input on the page.

function MessageBox() {
  const inputRef = useRef(null);

  return <input ref={inputRef} onBlur={() => inputRef.current?.focus()} />;
}

CodePudding user response:

First, you need to add an keydown event listener to the window and inside check if the document.activeElement ( which is the focused element ) tag name not an input, if yes, then focus the textarea

const textarea = document.querySelector('#textarea');

window.addEventListener('keydown', () => {
  const focusedElement = document.activeElement
  if (focusedElement.tagName.toLowerCase() !== 'input') {
    textarea.focus()
  }
})
input {
  margin-bottom: 20px;
  display: block;
}
<input type="text" />
<textarea id="textarea"></textarea>

CodePudding user response:

You need to listen to the key event from the window.

const MessageBox = () => {
  const [value, setValue] = useState('')

  useEffect(() => {
    const onKeyDown = e => {
      if (e.key === 'Enter') {
        return
      }
      if (e.key === 'Backspace') {
        return
      }
      
      // consloe.log(e) to see other options  
      setValue(v => v   e.code)
    }

    window.addEventListener('keydown', onKeyDown)
    return () => {
      window.removeEventListener('keydown', onKeyDown)
    }
  }, [])

  const onChange = e => { setValue(e.target.value) }

  return <input value={value} onChange={onChange} />
}

So basically you have two ways to change the value, one from old onChange and one from the key event from now on.

CodePudding user response:

Building on @Mina's answer, here's what I ended up doing with React:

function MessageBox() {
  const inputRef = useRef(null);

  useEffect(() => {
    function handler() {
      const focusedElement = document.activeElement;
      if (
        focusedElement?.tagName.toLowerCase() === "input" &&
        focusedElement?.id !== "messagebox"
      ) {
        // do nothing
      } else {
        inputRef.current?.focus();
      }
    }

    window.addEventListener("keydown", handler);

    return () => window.removeEventListener("keydown", handler);
  }, []);

  return <input ref={inputRef} id="messagebox" />;
}


  • Related