Most of us who use web browsers understand that the web UI only requires a single click on links, form buttons, and input fields. However, there are people who are used to double-clicking everything in the same way you double-click icons in an OS GUI. Sometimes this causes problems, specifically with shopping carts, where double-clicking can lead to the checkout form being submitted twice which results in duplicate orders.
I ran into this problem with Shopp, in a very specific situation where the server was responding slowly. Normally this kind of thing doesn’t happen, and I couldn’t reproduce the problem myself, but a few customers over a couple of days had managed to place duplicate orders. After checking the database I noticed that the transactions were usually 2-15 seconds apart, so I thought I’d disable the “Submit Order” button on the checkout form after it had been clicked once. Easier said than done.
Unfortunately, this isn’t as simple as using the disabled attribute on the button. Since there is some Javascript input validation, I needed to make sure that the form was validating first before disabling the button. Fortunately, I had spoken to the lead developer of Shopp about this a while back, so I knew that I needed to check `shopp.validate` which fires when the Submit Order button is clicked. If it validates correctly, then it submits the form data to the server. After some digging in the JS, I found the validation method and wrote some code to disable it after the button has been clicked once. Here’s the code:
<script type="text/javascript">// <![CDATA[
jQuery(document).ready(function($){
var form = $("#checkout.shopp"),
checkoutButton = $('.payoption-0 input');
form.on("submit.validate", function(e) {
if ( validate(this) ) {
form.unbind('shopp_validate');
checkoutButton.unbind("submit.validate").attr("disabled", "disabled").attr("value", "Processing...");
// set a timer to re-enable the button or maybe reload the page
setTimeout(timeouterr, 30000);
}
});
function timeouterr() {
$('.payoption-0').append('An error has occurred, and your order has not been sent in 30 seconds. Please <a href="javascript:location.reload();">reload the page</a> and try your transaction again.');
}
});
// ]]></script>
All you have to do is drop this code into the bottom of the checkout.php file in your theme/shopp directory.
The code runs when the “Submit Order” button is clicked, and it checks to make sure the form is valid. If it is, it disables the validate function, which posts the data to the server, and then it changes the button text to “Processing…” so the customer knows something is happening. In the event that something doesn’t happen after 30 seconds, the `setTimeout()` function will display a message below the button that says the order hasn’t gone through, and shows a link to reload the page.
This code has stopped the duplicate transaction issue I was seeing, and it offers a better user experience especially on slow sites where a customer might click on the submit button because it doesn’t look like anything is happening.