When you think ASP, think...
Recent Articles
All Articles
ASP.NET Articles
ASPFAQs.com
Message Board
Related Web Technologies
User Tips!
Coding Tips

Sections:
Sample Chapters
Commonly Asked Message Board Questions
JavaScript Tutorials
MSDN Communities Hub
Official Docs
Security
Stump the SQL Guru!
XML Info
Information:
Feedback
Author an Article
Technology Jobs
ASP ASP.NET ASP FAQs Message Board Feedback ASP Jobs
Print this page.
Published: Wednesday, October 04, 2006

Prevent Users from Submitting a Form Twice

By Scott Mitchell


Introduction
When a user clicks a submit button in a form, their browser makes a request back to the web server for the specified URL. On the web server, the user's input is processed and some action is taken based on the input. A database record might be added, an email might be sent, and so on. One potential issue that can arise is if a user submits a form, but there is a delay in getting back a response from the server. A user may think that the button click didn't "take", so they click it again. This can lead to two form submissions, resulting in two database records being added, two emails being sent, or whatever.

A recent Quick Tip at ASP101.com caught my eye the other day. The tip, titled Stop Users from Double Clicking, showed how to add a small bit of JavaScript to a form's submit button to prevent users from submitting a form more than once. The tip is remarkably simple - in the button's client-side onclick event, simply set the button's disabled property to true.

In my projects, I've always used a somewhat different method that is a little more involved. Rather than just disabling the submit button, I "freeze" the screen and show a message explaining that their data is being processed. Personally, I prefer the look and feel of the frozen screen, as it's more obvious that the data has been sent back to the server and is being processed. Also, it prevents the user from clicking other submit buttons that may be on the page. Read on to learn more about both of these techniques!

- continued -

'

Disabling a Button When Clicked
Many websites prevent a user from submitting a form more than once by disabling the submit button upon being clicked. Along with disabling the submit button, sites typically change the button's text from its initial value (such as "Submit") to some other value indicating than action has taken place (like "Submitted"). Changing the text and disabling the button can be accomplished using a couple lines of JavaScript in the button's client-side onclick event handler:

<script>
   function DisableButton(b)
   {
      b.disabled = true;
      b.value = 'Submitting';
      b.form.submit();
   }
</script>

<p>
   Click the button to see how it can be disabled and
   have its text changed when clicked...
</p>

<p>
   <input type="submit" name="SubmitButton" id="SubmitButton"
          value="Submit"
          onclick="DisableButton(this);" />
</p>
[View a Live Demo!]

The onclick event handler calls the DisableButton(button) function, passing in a reference to the button (this). In DisableButton(button), the button's disabled property is set to true and its value (the displayed button text) to "Submitted". To see this technique in action, check out this live demo.

Disabled Buttons and Data Sent on Form Submission
WARNING: Browsers do not send the data on form submission for those controls that are marked disabled. Since the button, when clicked, is marked as disabled via JavaScript, the browser will not include information that the button was clicked in the form submission. The result is that, if using ASP.NET, the corresponding Button Web control's Click event won't fire, since the ASP.NET engine isn't informed that the postback occurred because this button was clicked. If this is an issue, you have two options:
  1. Use the screen "freezing" technique discussed below, or
  2. Adjust the JavaScript in DisableButton(button) so that it doesn't disable the button but instead prohibits the user from subitting the form again. One option would be to have a "dummy" disabled button that is initially set to be invisible. Then, upon clicking the real submit button, the submit button could be hidden via CSS rules and the "dummy" button displayed.

"Freezing" the Page On Form Submission
One technique I've seen in commercial Web applications (such as FogBugz) to prevent double form submissions involves "freezing" the screen when the form is submitted. Specifically, the screen is frozen by placing a full screen, absolutely positioned element above all other elements on the page (specifically a <div> element). This covers up the content beneath the element and prevents the user from interacting with the form elements.

To start, we need to define some cascading stylesheet (CSS) classes that define the appearance of the frozen screen. There are three CSS clases:

  • FreezePaneOff - "hides" the <div> so that the page is interactive (i.e., not frozen)
  • FreezePaneOn - the frozen screen element is actually a full screen <div> with an inner <div> that displays a message (like "Processing Your Request"). This CSS class defines the settings for the outer <div>.
  • InnerFreezePane - specifies the style settings for the inner <div>, which shows a message to the user (like "Processing Your Request").
We also need our inner and outer <div> elements and a JavaScript function that, when invoked, freezes the screen by changing the <div>s' class attribute from the default (FreezePaneOff) to the CSS classes corresponding to the frozen frame (FreezePaneOn and InnerFreezePane).

Let's start with the CSS classes:

<style type="text/css">
   .FreezePaneOff
   {
      visibility: hidden;
      display: none;
      position: absolute;
      top: -100px;
      left: -100px;
   }

   .FreezePaneOn
   {
      position: absolute;
      top: 0px;
      left: 0px;
      visibility: visible;
      display: block;
      width: 100%;
      height: 100%;
      background-color: #666;
      z-index: 999;
      filter:alpha(opacity=85);
      -moz-opacity:0.85;
      padding-top: 20%;
   }

   .InnerFreezePane
   {
      text-align: center;
      width: 66%;
      background-color: #171;
      color: White;
      font-size: large;
      border: dashed 2px #111;
      padding: 9px;
   }
</style>

Note that the FreezePaneOff CSS class indicates a hidden element (visibility: hidden; display: none;). The FreezePaneOn CSS class, however, shows the element and positions it at the top of the page giving it a full width and height. The z-index value specifies the "layer" of the element on the page. The 999 value is used so that it appears above other elements on the page. The filter:alpha(opacity=85) and -moz-opacity:0.85 make the background pane translucent for Internet Explorer and Mozilla FireFox, respectively. Finally, the InnerFreezePane CSS class defines the syle settings for the inner message.

In addition to the CSS classes, we need to add the <div> elements to the page. Initially, the outer <div>'s class attribute should be set to FreezePaneOff. When the form is submitted, it will be changed (via JavaScript) to FreezePaneOn.

<div align="center" id="FreezePane" class="FreezePaneOff">
   <div id="InnerFreezePane" class="InnerFreezePane"> </div>
</div>

Finally, we need a bit of JavaScript that scrolls the browser to the top of the window (since the <div> is positioned at the top of the page) and updates the outer <div>'s CSS class. Additionally, we need to invoke this JavaScript method when the form is submitted (in the submit button's onclick event, for example).

<script language="JavaScript">
   function FreezeScreen(msg) {
      scroll(0,0);
      var outerPane = document.getElementById('FreezePane');
      var innerPane = document.getElementById('InnerFreezePane');
      if (outerPane) outerPane.className = 'FreezePaneOn';
      if (innerPane) innerPane.innerHTML = msg;
   }
</script>

<p>
   <input type="submit" name="SubmitButton" id="SubmitButton"
          value="Submit"
          onclick="FreezeScreen('Your Data is Being Processed...');" />
</p>
[View a Live Demo!]

Note that the FreezeScreen(msg) function accepts as input the message to display in the inner <div>. To see this script in action, check out the live demo.

Upon form submission, the screen becomes 'frozen.'

There are some shortcomings as well as loose ends that could be tied up with the frozen screen approach. For one thing, the screen really isn't frozen. The user can still scroll, still click HTML elements not covered by the outer <div>, can still hit the Back button, refresh the page, and so on. Also, I've not thoroughly tested this approach across a wide spectrum of browsers. It works on IE 6, FireFox 1.5, and Opera 9.0 (although the opacity setting doesn't work), but I'm uncertain to its support in older browsers. However, despite these potential shortcomings, this technique has worked well for me in my projects, and hopefully you can get some use out of it, too!

Happy Programming!

  • By Scott Mitchell


    Suggested Readings:

  • Stop Users from Double Clicking

  • Software Developer / Programmer - Distributed Systems (NYC)
    Next Step Systems
    US-NY-New York

    Justtechjobs.com Post A Job | Post A Resume


    ASP.NET [1.x] [2.0] | ASPMessageboard.com | ASPFAQs.com | Advertise | Feedback | Author an Article