jQuery Tutorial – Create Captcha without server-side code
Creating human validating fields (Captcha) is necessary to avoid robot spamming. While the general ones, like reCaptcha, are being bypassed by several services in the web, like De-Captcher, creating a new solution has come in need.
For the purpose of this tutorial we will be creating a simple sum of two numbers between 0 and 9.
First we create an html of the form we are about to use, note that we are adding the latest jquery library to the html:
<html> <head> <script src='http://code.jquery.com/jquery-latest.min.js'></script> </head> <body> <form name = "myForm" id = "myForm"> <table> <tr> <td>Name</td> <td><input type = "text" name = "Name" ></td> </tr> <tr> <td>Email</td> <td><input type = "text" name = "Email" ></td> </tr> <tr> <td colspan = "2" ><input type ="submit" value = "Submit" ></td> </tr> </table> </form> </body> </html>
After getting set up the html, we set up a template we are going to use for appending to the form. This will be of great use, since we can have several forms and instantiate them with the code we are about to generate.
TIP: If you are having some strings that are going to be of great use in several points of the code, those are constants! Don’t be afraid of using constants. They are your friends.
var captchaTemplate = '<tr><td align = "right">[Number1] + [Number2] = </td>' + '<td><input name = "captcha" > ' + '<input type="hidden" name = "captchaResult" value = "[CaptchaResult]" >' + '<span class = "error captcha" style = "display: none;" >[CaptchaError]</span>' + '</tr>';
Once we got the template for the captcha field, let’s start with the good thing. First we create the function that is going to rule over all captchas made in the site. The function is going to need two parameters: Target Form Selector, and the Error Message we are going to display.
First we set up a default value to the Error Message, with a cheap hack that checks if the type of the variable is defined or not. After setting up the default value, if needed, we create the random numbers using the Javascript function Math.random(), to get the numbers between 0 and 9, we multiply the value of Math.random() per 10 and then round the number with Math.floor(). Then we replace all in the previous template we made, that way we got the html we want!
TIP: When declaring a new variable, always use “var” before it, that way ie7 and ie8 will not crash.
function captcha( targetForm, errorMessage ) { if ( typeof errorMessage === "undefined" ) { var errorMessage = "Incorrect Captcha. Try Again."; } // Setting up the template with random numbers. var number1 = Math.floor( Math.random() * 10 ); var number2 = Math.floor( Math.random() * 10 ); var result = parseInt( number2 ) + parseInt( number1 ); var captchaTpl = captchaTemplate.replace( "[Number2]", number2 ); captchaTpl = captchaTpl.replace( "[Number1]", number1 ); captchaTpl = captchaTpl.replace( "[CaptchaResult]", result ); captchaTpl = captchaTpl.replace( "[CaptchaError]", errorMessage ); }
After setting up the html of the captcha we get the jQuery object of the form. Since we are getting the selector (ex. “#myForm”), it’s just needed to add it like this: $( targetForm ). Once we got the object, we find the row that has the input with type submit within the form (pretty neat, huh?), this part is easy. jQuery has a function called “.find”, so we first find the input[type=submit], and we use the “.closest” function to find the parent tr.
Once we got the html into a new variable, we remove it from the form and append to the table the captcha html and then the row we just delete :). There are many ways to do this, but I prefer doing this one, there is no margin of error, or we don’t lose anything.
TIP: Converting all the selector to jQuery object will avoid some unnecessary code writing.
function captcha( targetForm, errorMessage ) { if ( typeof errorMessage === "undefined" ) { errorMessage = "Incorrect Captcha. Try Again."; } // Setting up the template with random numbers. var number1 = Math.floor( Math.random() * 10 ); var number2 = Math.floor( Math.random() * 10 ); var result = parseInt( number2 ) + parseInt( number1 ); var captchaTpl = captchaTemplate.replace( "[Number2]", number2 ); captchaTpl = captchaTpl.replace( "[Number1]", number1 ); captchaTpl = captchaTpl.replace( "[CaptchaResult]", result ); captchaTpl = captchaTpl.replace( "[CaptchaError]", errorMessage ); // Convert the targetForm to an jQuery Object var formObj = $( targetForm ); // Obtain the html of the submit row var oldSubmit = formObj.find( "table input[type=submit]" ).closest( "tr" ).html(); // Remove the row which contains the submit button formObj.find( "table input[type=submit]" ).closest( "tr" ).remove(); // Append the captcha row and then the submit html formObj.find( "table" ).append( captchaTpl + oldSubmit ); }
Next, and final step, we do the submit handler for the form. It is quite easy, since the form’s html got the result for the sum we are doing, and the type is right there, we just compare the two.
function captcha( targetForm, errorMessage ) { if ( typeof errorMessage === "undefined" ) { errorMessage = "Incorrect Captcha. Try Again."; } // Setting up the template with random numbers. var number1 = Math.floor( Math.random() * 10 ); var number2 = Math.floor( Math.random() * 10 ); var result = parseInt( number2 ) + parseInt( number1 ); var captchaTpl = captchaTemplate.replace( "[Number2]", number2 ); captchaTpl = captchaTpl.replace( "[Number1]", number1 ); captchaTpl = captchaTpl.replace( "[CaptchaResult]", result ); captchaTpl = captchaTpl.replace( "[CaptchaError]", errorMessage ); // Convert the targetForm to an jQuery Object var formObj = $( targetForm ); // Obtain the html of the submit row var oldSubmit = formObj.find( "table input[type=submit]" ).closest( "tr" ).html(); // Remove the row which contains the submit button formObj.find( "table input[type=submit]" ).closest( "tr" ).remove(); // Append the captcha row and then the submit html formObj.find( "table" ).append( captchaTpl + oldSubmit ); // Set up the submit handler formObj.submit( function( e ) { // Set up the jquery object var myForm = $( e.target ); // Get the values to compare var result = myForm.find( "input[name=captchaResult]" ).val(); var humanRes = myForm.find( "input[name=captcha]" ).val(); // Compare the input value and the correct value if ( result == humanRes ) { // It is correct! Submit the Form! FIRE! myForm.submit(); } else { // It is incorrect! Show the error field, and stop the submit :( e.preventDefault(); myForm.find( "span.captcha" ).show(); } }); }
Finally, we got all we need in a function, the only thing missing is the actual call. So inside a $( document ).ready, we call the function. The final html should look like this:
<html> <head> <script src='http://code.jquery.com/jquery-latest.min.js'></script> <script type="text/javascript"> var captchaTemplate = '<tr><td align = "right">[Number1] + [Number2] = </td>' + '<td><input name = "captcha" > ' + '<input type="hidden" name = "captchaResult" value = "[CaptchaResult]" >' + '<span class = "error captcha" style = "display: none;" >[CaptchaError]</span>' + '</tr>'; function captcha( targetForm, errorMessage ) { if ( typeof errorMessage === "undefined" ) { var errorMessage = "Incorrect Captcha. Try Again."; } // Setting up the template with random numbers. var number1 = Math.floor( Math.random() * 10 ); var number2 = Math.floor( Math.random() * 10 ); var result = parseInt( number2 ) + parseInt( number1 ); var captchaTpl = captchaTemplate.replace( "[Number2]", number2 ); captchaTpl = captchaTpl.replace( "[Number1]", number1 ); captchaTpl = captchaTpl.replace( "[CaptchaResult]", result ); captchaTpl = captchaTpl.replace( "[CaptchaError]", errorMessage ); // Convert the targetForm to an jQuery Object var formObj = $( targetForm ); // Obtain the html of the submit row var oldSubmit = formObj.find( "table input[type=submit]" ).closest( "tr" ).html(); // Remove the row which contains the submit button formObj.find( "table input[type=submit]" ).closest( "tr" ).remove(); // Append the captcha row and then the submit html formObj.find( "table" ).append( captchaTpl + oldSubmit ); // Set up the submit handler formObj.submit( function( e ) { // Set up the jquery object var myForm = $( e.target ); // Get the values to compare var result = myForm.find( "input[name=captchaResult]" ).val(); var humanRes = myForm.find( "input[name=captcha]" ).val(); // Compare the input value and the correct value if ( result == humanRes ) { // It is correct! Submit the Form! FIRE! myForm.submit(); } else { // It is incorrect! Show the error field, and stop the submit :( e.preventDefault(); myForm.find( "span.captcha" ).show(); } }); } $( document ).ready( function() { captcha( "#myForm" ); }); </script> </head> <body> <form name = "myForm" id = "myForm"> <table> <tr> <td>Name</td> <td><input type = "text" name = "Name" ></td> </tr> <tr> <td>Email</td> <td><input type = "text" name = "Email" ></td> </tr> <tr> <td colspan = "2" align = "center" ><input type ="submit" value = "Submit" ></td> </tr> </table> </form> </body> </html>
Thank you for reading this quick tuto. I will be writing more quick tutos, and some more extensive 🙂
Here at Psynapsis.net, we can develop all the things you need, from simple javascript to extensive jQuery libraries.