Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent onclick event on a button from firing when hitting Enter in a different box

I need to have a user input field in the #wmd-button-bar of the SE editor, along with a button. The user can enter some data in the input field, and then press a button to process that data. I am using a userscript to achieve this. I have created a separate MVCE of that, and here is its direct install link for Tampermonkey/Greasemonkey.

To reproduce the issue, install the userscript. Reload this page and then click "Edit". You'll notice a new blank input box with a button. Focus the the "Edit summary" box blank, leave it blank, and hit Enter. Instead of submitting the answer box, your caret will now instead focus on the new blank input box.

The same happens if you press Enter inside the "Question title" box.

From the console.log messages, you'll notice that there has been instead a MouseClick event on the button! This is not expected behavior. In fact, how is this even possible? We just pressed Enter inside the Edit summary box, and didn't even touch either the new blank input or its button. How did it then register a mouse click?

How to fix this?

Note: The e.preventDefault(); inside the button onclick handler is necessary. Otherwise, when the user presses the button to process their input data, the answer box submits itself instead.


The Userscript Code:

function createModal(buttonBar){
    var div = document.createElement("div"),
        input = document.createElement("input"),
        btn = document.createElement("button");

    div.id = "box";

    input.type = "text";

    btn.innerHTML = "Button";
    btn.onclick = function(e){
        e.preventDefault();
        console.log("I was called");
        input.focus();
        console.dir(e);
        console.trace();
    };

    div.appendChild(input);
    div.appendChild(btn);

    return div;
}

setInterval(function () {
    var cont = document.querySelector(".wmd-container:not(.processed)"), ul, buttonBar, div;

    if (cont && (ul = cont.querySelector(".wmd-button-bar ul"))) {
        cont.classList.add("processed");

        buttonBar = cont.querySelector("div[id^=wmd-button-bar]");

        div = createModal(buttonBar);
        buttonBar.appendChild(div);
    }
}, 500)
like image 669
Gaurang Tandon Avatar asked Jun 09 '18 05:06

Gaurang Tandon


People also ask

How do I stop onclick event?

Bind both handlers with the . click() function and whichever one you bind first can call stopImmediatePropogation() to prevent the second one from running. (Or combine them into a single handler.)

How do I prevent a parent's onclick event from firing when a child anchor is clicked?

By a adding an onClick function for the child modal (content div) mouse click events are prevented to reach the 'closeLogin' function of the parent element. This did the trick for me and I was able to create a modal effect with 2 simple divs.

What's the difference between onclick ={ () => function ()} and onclick function?

The difference is the first one has the parentheses and the second one doesn't.

Can there be 2 onclick events?

So the answer is - yes you can :) However, I'd recommend to use unobtrusive JavaScript.. mixing js with HTML is just nasty.


2 Answers

The short and simple answer, is to force type for your button element:

<button type="button"></button>

It defaults to type="submit", and that's why it acts accordingly.

like image 154
Ilia Avatar answered Oct 11 '22 16:10

Ilia


Its default HTML behaviour. All the buttons inside a form are of type="submit". On pressing enter, the most recent button of the form is clicked and their handlers are called, by default. To fix this, the buttons are created with type="button".

console.log(document.querySelector("#a").type)
console.log(document.querySelector("#b").type)
console.log(document.querySelector("#c").type)
<form>
    <input type="text">
    <button id="a" onclick="console.log('a')">Submit type</button>
    <button id="b" onclick="console.log('b')" type="button">Button type</button>
    <input id="c" type="submit" value="Input Submit type">
</form>

You can refer this to understand the behaviour of <button> and <input type="button">.

If you just check in console like, document.querySelector("#box").children[1].type it will show as submit.

Button, by default, acts as submit type unless it is specified explicitly (either submit(default)/reset/button). Just run document.querySelector("#box").children[1].type=button. You find it working as expected.

The behaviour is same in cross-browser and tested in Firefox Nightly (developer version), Chrome and Safari and works a little bit different in IE.

Also you can see the click is by default by seeing console.log(event.detail) is 0 as it is triggered internally. When triggered with a left click, it would be 1. MDN Docs on click event

like image 40
Vignesh Raja Avatar answered Oct 11 '22 16:10

Vignesh Raja