5

I'm learning JavaScript and am unable to make a button inside of a form that doesn't submit the form. There is a similar question here but the most popular answer to specify type="button" doesn't work in my case and other answers involve jQuery, which I would like to leave out for now.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html>
<head>
<script type="text/javascript">
        function submit(){
                alert("Yo")
        }
</script>
</head>

<body>
<form name="myForm" onsubmit="submit()">
        <input type="button" value="Submit!" onClick="submit()" />
</form>
</body>
</html>
Community
  • 1
  • 1
MANA624
  • 986
  • 4
  • 10
  • 34
  • 3
    Since you're not using a `type="submit"` the only reason your form would submit anything is because you literally call the `submit()` method when the button is clicked. (well, sort of. it's actually form.submit()). By default, a input of `type="button"` will not do a form submission unless you literally call `form.submit()`. – Tibrogargan Jul 10 '16 at 21:23
  • @Tibrogargan that is the problem. Once I changed the function name it worked perfectly! If you make it an answer I can accept it. – MANA624 Jul 10 '16 at 21:30
  • This is actually a really interesting question. Since functions are scoped at the window level you would expect your `onClick="submit()"` to use the `window.submit()` method - but it's resolving to `form.submit()` when the input tag is created because the context was changed to the form. I can't find that behavior documented anywhere - it might actually be browser dependent (or I just don't know the right place to look) – Tibrogargan Jul 10 '16 at 22:01
  • @Tibrogargan I tested in both Mozilla and Chrome, though I haven't tried in IE. But if you do find the documentation anywhere please let me know, I'd love to read it! – MANA624 Jul 11 '16 at 05:57
  • 1
    Turns out it's by design. [Scope Changes During HTML Parsing](/questions/38296881/scope-changes-during-html-parsing) – Tibrogargan Jul 11 '16 at 06:00

8 Answers8

3

Since you're not using a type="submit" the only reason your form would submit anything is because you're literally calling the submit() method when the button is clicked. (well, sort of. It's actually form.submit() - the method you created is window.submit()).

By default, an input of type="button" will not do a form submission unless you literally call form.submit()

Tibrogargan
  • 4,508
  • 3
  • 19
  • 38
2

Pass along the event as an argument in your submit function, and prevent its default behaviour:

function submit(event) {
    event.preventDefault();
    alert('Yo');
}

onClick='submit(event)'
1sloc
  • 1,180
  • 6
  • 12
2

Dating from the introduction of Javascript by Netscape Corporation, form element event handlers defined as HTML attribute values were provided with a special scope chain which searches properties of the element clicked and the form element ahead of searching the global object. [This was a convenience for web programmers and predated the introduction of a Document Object Model with standardized methods for access and manipulation.] Hence

<input type="button" value="Submit!" onClick="submit()" />

when clicked executes the anonomous function created from the HTML attribute string:

function( event) { submit()}

which searches its scope chain for submit and finds it as a property of the enclosing form object. Possible solutions include

  • explicitly specifying the global version of the function to execute:

        onclick="window.submit()"
    
  • naming the global function something else, say "preSubmit", which does not conflict with the property of the form object:

        onclick="preSubmit()"  
    
  • adding the click event handler to the button in javascript after the button element has been created (only function specified in HTML have a special scope chain).

Section `19.1.6. Scope of Event Handlers" within chapter 19 of "Javascript the Definitive Guide" from O'Reilly is the only link that I have been able to find which discusses this.


updated after @progysm's comment on another answer

The scope chain of an HTML provided event handler is now covered in the HTML5 standard, under internal raw uncompiled handler, list item 1.10, which indicates the lexical scope of the handler includes the element clicked, the form it belongs to (if any) and the document object. I would caution against relying on this too heavily: some browsers used to include every parent object of a clicked element in its scope chain, not just its form and document.

traktor
  • 17,588
  • 4
  • 32
  • 53
1

To prevent your button from submitting, you can either:

  1. Use preventDefault() on the onsubmit event of the <form> or
  2. Use return false at the end of the operation on the onclick event of the button.

The code:

<html>
    <head></head>

    <body>
        <form name = "myForm" method = "POST">
            <input name = "button" type="submit" value="Submit!"/>
        </form>

        <script type = "application/javascript">
             document.forms.myForm.onsubmit = function(e) {
                 e = e || event;
                 e.preventDefault();
             }

             document.forms.myForm.button.onclick = function () {
                 // Your code
                 return false; // Prevents the button from trying to submit
             }
        </script>
    </body>
</html>

Notes:

  • Be sure to use the method attribute in the <form> tag as it's required.
  • e = e || event means that e will be equal to e in all the browsers that recognise it and equal to event in browsers that recognise event.
  • document.forms.[form name].[input name] is another way to get an element based on its name, in contrast to document.getElementById() which requires the id of the element, which have not set in your HTML.

You can test the code's functionality live with the following snippet:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html>
        <head></head>

        <body>
            <!-- The form we don't want to submit -->
            <form name = "myForm" method = "POST">
                <input name = "button" type="submit" value="I will not submit!"/>
            </form>
          
            <!-- The form we want to submit -->
            <form name = "myForm2" method = "POST">
                <input name = "button2" type="submit" value="I will submit!"/>
            </form>

            <script type = "application/javascript">
                 // For the form we don't want to submit
                 document.forms.myForm.onsubmit = function(e) {
                     e = e || event;
                     e.preventDefault();
                 }

                 document.forms.myForm.button.onclick = function () {
                     console.log("NOT Submitted!");
                     return false;
                 }
                 
                 // For the form we want to submit
                 document.forms.myForm2.button2.onclick = function () {
                     console.log("Submitted!");
                 }
            </script>
        </body>
    </html>
Angel Politis
  • 10,955
  • 14
  • 48
  • 66
0

function onFormSubmit()
{
  console.log('FORM SUBMITTED');
  return false;
}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html>
<body>
  <form name="myForm" onsubmit="return onFormSubmit()">
    <input type="submit" value="Submit form! [input type = submit]" /><br />
    <input type="button" value="Submit form! [input type = button, onclick = form.submit]" onClick="return onFormSubmit();" /><br />
    <!-- in real test change onClick behavior 
    return onFormSubmit(); 
    to:
    form.submit();
    Here I used onFormSubmit() because when you calling form.submit() browser doesn't dispatch onsubmit event -->
    <button>Submit form! [button]</button><br />
    <a href="#" onClick="return onFormSubmit();">Submit form! [a, onclick = form.submit]</a><br /><br />
    <input type="button" value="Click me, no submit! [input type = button]" /><br />
  </form>
</body>
</html>
Leonid Zakharov
  • 940
  • 1
  • 6
  • 11
0

If you wish to conditionally consume the event or not, simply return true or false from your handler function, like so...

JavaScript:

function validate() {
    var valid = true;
    // the following two validation functions would return a Boolean.
    valid = valid && validateUsername();
    valid = valid && validatePassword();
    // If validation is fine, return true and this allows post to continue.
    // If validation is not fine, return false and this disallows the submission from going ahead.
    return valid;
}

HTML:

<form name="frmTest" id="frmTest"
    method="post" action="example.action"
    onsubmit="return validate();">
</form>

If you don't need it to be conditional, just return false, of course.

ManoDestra
  • 6,325
  • 6
  • 26
  • 50
0

This solution works in native javascript. Doesn't prevent return key in inputs, it does what it should - stop a form from submitting on enter

function preventReturnKeyFormSubmit(){
    //listen to key press events
    window.addEventListener('keydown', function(e){
        //set default value for variable that will hold the status of keypress
        pressedEnter = false;

        //if user pressed enter, set the variable to true
        if(event.keyCode == 13)
            pressedEnter = true;

        //we want forms to disable submit for a tenth of a second only
        setTimeout(function(){
            pressedEnter = false;
        },100)

    })

    //find all forms
    var forms = document.getElementsByTagName('form')

    //loop through forms
    for(i = 0; i < forms.length; i++){
        //listen to submit event
        forms[i].addEventListener('submit', function(e){
            //if user just pressed enter, stop the submit event
            if(pressedEnter == true) {
                e.preventDefault();
                return false;
            }
        })
    }

}
//run this function inside document onload/domready/ or if using jquery .ready()
preventReturnKeyFormSubmit()
mate.gvo
  • 1,093
  • 14
  • 20
-1

Simply make it return the function, and return false

<script type="text/javascript">
        function submit(){
                alert("Yo");
return false;
        }
</script>
</head>

<body>
<form name="myForm" onsubmit="submit()">
        <input type="button" value="Submit!" onClick="return submit()" />
</form>
</body>
</html>
MoustafaS
  • 1,991
  • 11
  • 20
  • 1
    This won't work @MoustafaS, because submit() inside onClick is form.submit() (see how the scope is modified in inline event handler in HTML5. – progysm Jul 10 '16 at 23:02