glocore
glocore

Reputation: 2164

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

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()} />;
}

Upvotes: 0

Views: 32

Answers (3)

glocore
glocore

Reputation: 2164

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" />;
}


Upvotes: 0

windmaomao
windmaomao

Reputation: 7680

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.

Upvotes: 0

Mina
Mina

Reputation: 17604

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>

Upvotes: 1

Related Questions