Page 1 of 1

Preventing Default Action Rate Topic: -----

#1 andrewsw  Icon User is offline

  • lashings of ginger beer
  • member icon

Reputation: 6340
  • View blog
  • Posts: 25,562
  • Joined: 12-December 12

Posted 30 April 2016 - 03:56 AM

Prevent default behaviour of a-links and forms

Use proper, modern, event handling with addEventListener and e.preventDefault(), optionally considering e.stopPropagation() or e.stopImmediatePropagation(). Understand, and usually avoid, return false.

return false is over-used to prevent the default following of a href for an a-link, or the submission of a form. It is really a hang-over from older approaches.

Useful links:

jQuery Events: Stop (Mis)Using Return False
Event order :quirksmode
The difference between ‘return false;’ and ‘e.preventDefault();’ in jQuery
How do I cancel form submission in submit button onclick event?
Early event handlers :quirksmode
Href attribute for Javascript links: “#” or “javascript:void(0)”?

Disabling a-link href entirely

If you want to completely disable the href of an a-tag then use javascript:void(0). This is another hang-over from earlier code, but it works consistently (see the last article linked above).
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Preventing Defaults</title>
</head>
<body>
<h1>Preventing Defaults</h1>
<a href="javascript:void(0);" onclick="doSomethingElse();">Will not follow!</a>
<script>
function doSomethingElse() {
    console.log("something else..");
}
</script>


(full code shown at the bottom of this tutorial)

This, and the following code, uses the 'onclick' attribute, mixing the HTML and Javascript. Instead, use modern event handling with addEventListener as demonstrated further below.

However, the important question is, why would you use an a-link if you are completely disabling its functionality? In modern Javascript click events can be added to any element, and CSS can be used if you want the element to look and behave like a link. Don't use an a-link only to fight against its natural behaviour.

Optionally disabling href
<label><input type="checkbox" id="follow" value="follow"> Follow link?</label>
<hr>
<a href="somepage.html" onclick="return doSomething();">May not follow!</a>
<script>
function doSomething() {
    if (document.getElementById('follow').checked) {
        return true; // follow
    } else {
        return false; // cancel href
    }
}
</script>


(the checkbox is also referred to in later code samples)

Notice importantly that the onclick attribute will return the value that the function returns. Also, it is not necessary for the function to return true, the link will still be followed.

Use modern event handling

Keep our Javascript separate from our HTML using addEventListener.
<h2>Event Handling</h2>
<a href="anotherpage.html" id="handling">Event handling</a>
<script>
document.getElementById('handling').addEventListener('click', function (e) {
    if (document.getElementById('follow').checked) {
        // do nothing, link will be followed
    } else {
        e.preventDefault();
        // optional
        //e.stopPropagation(); // ..to other event handlers
        //return false; //doesn't work in vanilla JS anyway
    }
}, false);
</script>


Try using return false instead of e.preventDefault(), it doesn't work.

stopPropagation will stop the event from propagating (bubbling up) to other, parent, elements. The argument 'false' for addEventListener says 'don't use (IE) capturing', so we don't have to consider IE specifics like 'cancelBubble', as discussed in the first quirksmode article above.

e.stopImmediatePropagation() (discussed in the first article above) stops propagation, even for events registered with the same element. Of course, it is preferable that only a single event would be registered with any one element, but, with more complex pages, this won't always be the case. (Note that events on an element are fired in the order they were bound.)

The older approach (than addEventListener) was to assign directly to the onclick attribute of an element. In which case, return false does have the desired effect, seen here:
<h3>Old School</h3>
<p>Assigning to the onclick attribute.</p>
<a href="somepage2.html" id="oldschool">Old School</a>
<script>
document.getElementById('oldschool').onclick = doThis;

function doThis(e) {
    if (document.getElementById('follow').checked) {
        // do nothing, follow
    } else {
        return false; // cancel href
    }
}
</script>


We shouldn't use this approach, use addEventListener. One main reason not to is that we can only assign a single handler for an event in this way, and it gives us limited control.

jQuery version

Here is the jQuery version of the above event handler code:
<h3>jQuery Version</h3>
<a href="anotherpage2.html" id="handling2">Event handling (jQuery)</a>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script>
<script>
$('#handling2').on('click', function (e) {
    if ($('#follow').is(':checked')) {
        // do nothing, will follow
    } else {
        e.preventDefault();
        //return false; // works, but use preventDefault instead
    }
});
</script>


jQuery on()

In this case return false would work because, as discussed in the first article, it achieves these three things in jQuery:

  • event.preventDefault();
  • event.stopPropagation();
  • Stops callback execution and returns immediately when called.

but, as also discussed, you usually only need preventDefault().

Prevent form submission

Preventing a form submission is following very similar guidelines to those already discussed for the following of a link.

First and foremost though, don't use the click event of the submit button, use the submit event of the form.
<h2>Forms</h2>
<form id="ffirst" action="processpage.php" method="GET">
<label>Enter number 4 <input type="text" id="four" name="four" value="0"></label>
<input type="submit" name="submitted" value="Submit">
</form>
<script>
document.getElementById('ffirst').addEventListener('submit', function (e) {
    if (document.getElementById('four').value === '4') {
        // form will submit as normal
    } else {
        e.preventDefault();
    }
}, false);
</script>


preventDefault() can occur at any point, but usually you are validating the form data, so a typical last line of the code would be something like if (!isValid) e.preventDefault();.

If the form data is processed using Ajax (or another submission-less technology) then e.preventDefault(); would typically be the first statement.

Here is a jQuery version of the above code:
<h3>Form (jQuery)</h3>
<form id="fsecond" action="processpage.php" method="GET">
<label>Enter number 5 <input type="text" id="five" name="five" value="0"></label>
<input type="submit" name="submitted" value="Submit">
</form>
<script>
$('#fsecond').on('submit', function (e) {
    if ($('#five').val() === '5') {
        // form will submit as normal
    } else {
        e.preventDefault();
    }
});
</script>




For the sake of completeness, I include the code if you were using the (inline) onsubmit attribute of the form (this isn't included in the final code):
<form action="processpage.php" method="GET" onsubmit="return checkIt();">
    <input type="text" id="dummy">
    <input type="submit" name="submit" value="Submit">
</form>
<script>
function checkIt() {
    document.getElementById('dummy').value = "still here";
    return false;
}
</script>


Again, notice the use of return checkIt(); for the attribute.



Here is the full code, in the spoiler:

Spoiler

Please don't be shy of criticising my tutorial, or suggesting improvements in either the samples or my descriptions. I want it to be correct.

Is This A Good Question/Topic? 0
  • +

Page 1 of 1