javascripthtmlevents

Calling dispatchEvent(clickEvent) on a textbox doesn't work


I have a very contrived example where I want to programmatically generate a click event on a textbox when a user clicks on a button. I can see that the textbox gets the event but the focus doesn't change to the textbox.

I know I can call focus() but my goal is to use dispatchEvent and mouse events only. This comes from a large app where I have a transparent IFrame over the whole page (imagine a transparent layer with some custom content on top of Google Maps). The IFrame's content can come from a 3rd party which may choose to either handle the click event, or propagate it up to the parent (kind of like bubbling up but across frame boundaries). While doing so, I noticed that some elements on the parent page (like text boxes and buttons) don't behave as I would normally expect so I produced this small example to illustrate the problem.

function handleClick(event)
{
    let textbox = document.getElementById('text');
    let rect = textbox.getBoundingClientRect();            

    let newEvent = new MouseEvent('click', {
        clientX: rect.x + 5,
        clientY: rect.y + 5,
        x: rect.x + 5,
        y: rect.y + 5,
        pageX: rect.x + 5,
        pageY: rect.y + 5
    });

    textbox.dispatchEvent(newEvent);
}
<input type="text" id="text" onclick="console.log('clicked')" /> 

<button onclick="handleClick(event)">Click</button>


Solution

  • Call focus() (MDN) on the element you want to focus.

    You can also use click() (MDN) to simulate a mouse click.

    document.querySelector('#button').addEventListener('click', () => {
      const inp = document.querySelector('#inp')
      inp.focus()
      inp.click()
    })
    <input type="text" id="inp" onclick="console.log('clicked')" /> 
    <button id="button">Click</button>

    Here it is using your code example.

    function handleClick(event)
    {
        let textbox = document.getElementById('text');
        let rect = textbox.getBoundingClientRect();            
    
        let newEvent = new MouseEvent('click', {
            clientX: rect.x + 5,
            clientY: rect.y + 5,
            x: rect.x + 5,
            y: rect.y + 5,
            pageX: rect.x + 5,
            pageY: rect.y + 5
        });
    
        textbox.dispatchEvent(newEvent);
    }
    
    function clickCallback(event) {
      event.target.focus()
      event.target.click()
    }
    <input type="text" id="text" onclick="clickCallback(event)" /> 
    <button onclick="handleClick(event)">Click</button>