skip to Main Content

By accident I noticed a html button on a webpage which I could click programmatically as follows

button.click();

But when I did

const rect = btn.getBoundingClientRect();

const options = {
    bubbles: true,
    cancelable: true,
    screenX: rect.x,
    screenY: rect.y,
};
const e = new Event('click', options)
btn.dispatchEvent(e);

it didn’t work. Apparently there is a difference between the two. Can someone explain what that might be?

3

Answers


  1. Both work for me

    Notice that both of them have to be triggered by a user interation

    function clickOtherButton() {
      const rect = btn.getBoundingClientRect();
    
      const options = {
        bubbles: true,
        cancelable: true,
        screenX: rect.x,
        screenY: rect.y,
      };
      const e = new Event('click', options)
      btn.dispatchEvent(e);
    }
    <button id="btn" onclick="alert(1)">btn</button>
    <button onclick="clickOtherButton()">click me</button>
    function clickOtherButton() {
      btn.click()
    }
    <button id="btn" onclick="alert(1)">btn</button>
    <button onclick="clickOtherButton()">click me</button>
    Login or Signup to reply.
  2. The following experiment shows up a difference between the methods (there may be others):

    • Clicking the button itself produces an event with pointerType: "mouse".
    • The click() method produces an event with pointerType: "".
    • Dispatching an Event (or even a MouseEvent) gives pointerType: undefined.
    var btn = document.querySelector("button");
    btn.addEventListener("click", function(event) {
      console.log(event.pointerType);
    });
    <button>Event Target</button>
    <span onclick="btn.click()">Click</span>
    <span onclick="btn.dispatchEvent(new Event('click'))">Dispatch</span>
    <span onclick="btn.dispatchEvent(new MouseEvent('click'))">DispatchMouse</span>
    Login or Signup to reply.
  3. Event can’t be used to click a submit button

    button.dispatchEvent(new Event('click'));        // <-- this fails
    button.dispatchEvent(new PointerEvent('click')); // <-- this works
    

    A key piece of information is that the button on the page is a form submit button. This why the page reloads as noted in the question.

    <button type="submit">Zoek</button>
    

    Both the click method and dispatchEvent will cause a click event. No problems with this part.

    The actual problem is that OP is using a generic base Event to click a form submit button. This doesn’t work because the generic event won’t cause a submit event to be fired after the click.

    Yet, if we instead use PointerEvent the form is submitted and the page reloads:

    Test Snippet

    let form = document.querySelector('form');
    let button = document.querySelector('button[type=submit]');
    
    form.addEventListener('submit', (e) => {
      e.preventDefault(); // do not reload page
      console.log(`${e.target.tagName} event: ${e.type}`);
    })
    
    button.addEventListener('click', (e) => {
      // e.preventDefault(); // <-- prevents form submit on click
      console.log(`${e.target.tagName}, event: ${e.type}`);
    
    })
    
    console.log('Using click method');
    button.click();
    
    console.log('Using Event - no following submit');
    button.dispatchEvent(new Event('click', {bubbles: true, cancelable: true}));
    
    console.log('Using PointerEvent');
    button.dispatchEvent(new PointerEvent('click', {bubbles: true, cancelable: true}));
    
    console.log('end test');
    .as-console-wrapper {
      max-height: 100% !important;
    }
    <form>
      <button type="submit">Zoek</button>
    </form>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search