skip to Main Content

I currently have a page that is rendered with tech I won’t delve in for now, because it’s irrelevant I believe.

In this page, I have a bunch of controls (simple text inputs).
There’s also a side panel where the help is displayed.
When the user focuses on one of the controls, the side panel shows the help for that control. When no control is in focus (as when the page is first accessed), a default help is shown.

I handle this using focusin/focusout events. When one of the control ids is focused in, I display their help.

To restore the help at the page level, the user technically can click anywhere, losing the focus on the controls. So I added the focusout event to detect that, and restore the
default page.

The problem is that if the user has the focus on one control, and clicks on another control, for a brief second the default help is shown. This is of course to be expected, since I am doing a focusout on one control (which displays the default help) followed by a focusin on the other control (which displays the help for that control).

How can I prevent the flickering? In other words, how do I check not really the focusin/out, but the focuschange, knowing from where I come from in the focus, and where I am going?

2

Answers


  1. The code below effectively creates a "focus change" detection by using a delayed action on focusout and clearing that action if a new control receives focus quickly enough.

    let helpTimeout;
    
    function updateHelpTextForControl(controlId) {
        // Update the help text for the focused control
    }
    
    function setDefaultHelpText() {
        // Set the default help text
    }
    
    document.querySelectorAll('.control').forEach(control => {
        control.addEventListener('focusin', function() {
            // Clear any pending timeout to reset help text
            clearTimeout(helpTimeout);
    
            // Update the help text for this control
            updateHelpTextForControl(this.id);
        });
    
        control.addEventListener('focusout', function() {
            // Set a delay before resetting to the default help text
            helpTimeout = setTimeout(setDefaultHelpText, 100); // adjust delay as needed
        });
    });
    
    Login or Signup to reply.
  2. You could use the event of focusout to check e.relatedTarget?.nodeName to see if the newly focus is an element which has a custom Help page.

    Then instead of setting the default help, instantly set the new help of the new focus element.

    const i = document.querySelector('input');
    i.addEventListener('focusout', (e) => {
        if (e.relatedTarget?.nodeName === 'INPUT') {
            console.log('Lost focus, but got focus on other input, setting correct Help');
        } else {
            console.log('Lost focus, setting default help');
        }
    })
    #left {
      width: 100px;
      height: 30px;
      border: 2px dashed yellow;
      font-size: 25px;
      margin-bottom: 15px;
    }
    <div id='left'>Foo</div>
    
    <input id='a' />
    <input id='b' />
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search