admin管理员组

文章数量:1223212

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)

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)
Share Improve this question edited Jun 15, 2018 at 13:58 Gaurang Tandon asked Jun 9, 2018 at 5:20 Gaurang TandonGaurang Tandon 6,75311 gold badges50 silver badges94 bronze badges 4
  • 1 Have you tried defining a keypress event for pressing the enter key and putting e.preventDefault() in the callback? This might help. – Marzieh Bahri Commented Jun 18, 2018 at 6:36
  • 1 @MarziehBahri Sorry, but, I don't wish to disable the default behavior of pressing the Enter key in the Edit summary box to submit the post. So, I cannot do that. – Gaurang Tandon Commented Jun 18, 2018 at 13:56
  • 1 One possibility can be - form containing only input text gets submitted on Enter press. And this is triggering all submit activities like click maybe. If this is the case then you can either remove parent form element or have one more hidden input element. Or add stopPropagation to trigger only one submit event through enter press. – Harshali Talele Commented Jun 19, 2018 at 11:11
  • 1 One patchwork you can try is add an event handler for enter press on the input box like - function preventSubmission(e) { e.preventDefault(); } Or set a semaphore/flag in enter handler and check it inside click handler and prevent action accordingly. – Harshali Talele Commented Jun 19, 2018 at 11:15
Add a comment  | 

3 Answers 3

Reset to default 8

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

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.

i tried the following code in firefox browser and it works as expected.

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

    div.id = "box";

    input.type = "text";
    btn.type = "button";

    btn.innerHTML = "Button";
    btn.onclick = function(e){
        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);

notice that i have set the btn.type="button"; this makes sure the form is not submitted and also removed e.preventDefault(); as button will never submit the form now.

keep in mind that by default if you don't give a type to a button element then it will behave like a submit button.

also the MouseClick event was firing because the click event is triggered on submit buttons present within the form when submitting the form. as you had the button without the type attribute it was working like a submit button. so the MouseClick event was fired when you hit enter (as its submitting the form).

you can verify this by adding an onclick handler from your browser developer tool to the Save edits submit button and hit enter on the text field.

本文标签: