UNPKG

js-captcha

Version:

Simple captcha component written in pure JavaScript with no dependencies based on canvas element

482 lines (403 loc) 16 kB
<!doctype html> <html lang='en'> <head> <title>jCaptcha - Simple captcha component written in pure JavaScript with no dependencies</title> <meta charset='utf-8'> <meta name='description' content='Simple captcha module written in pure JavaScript with no dependencies...'> <meta name='robots' content='index, follow'> <meta name='viewport' content='width=device-width, initial-scale=1'> <link href="https://fonts.googleapis.com/css?family=Yesteryear" rel="stylesheet"> <link href="https://www.rvdizajn.com/jpopup/css/jPopup.css" rel="stylesheet"> <script async defer src="https://buttons.github.io/buttons.js"></script> </head> <style> /*** DEMO only ***/ html { font-size: 62.5%; } html, body { margin: 0; padding: 0; font-family: Arial, "Helvetica Neue", Helvetica, sans-serif; color: #ddd; background-color: #292b2b; text-align: center; } header { margin: 50px auto 10px auto; text-align: center; } h1 { font-size: 17px; margin: 5px auto 15px; font-weight: normal; } h2 { font-size: 100px; line-height: 1; margin: 0 auto; font-family: 'Yesteryear', cursive, serif; color: #e8d639; text-shadow: 3px 5px 2px #1f1f1f; } header p { font-size: 14px; margin: 18px 20px 0 20px; line-height: 1.5; color: #848484; border-bottom: 1px solid #464646; display: inline-block; } main { position: absolute; left: 50%; top: 50%; width: 470px; height: 60px; margin: -30px 0 0 -235px; border-radius: 4px; } .form { box-shadow: 2px 4px 2px #1f1f1f; position: relative; border-radius: 4px; } .jCaptchaCanvas { position: absolute; top: -25px; left: 15px; } .jCaptcha { padding: 20px 25px 20px 20px; font-size: 15px; width: 320px; height: 60px; box-sizing: border-box; outline: none; border-radius: 4px 0 0 4px; border: none; vertical-align: middle; transition: all 150ms linear; box-shadow: 0 0 8px #4e4706; } .jCaptcha:focus, .jCaptcha:focus~.button { box-shadow: 0 0 8px #a79816; } .jCaptcha.error, .jCaptcha.error~.button { box-shadow: 0 0 8px #c5391a; } .jCaptcha.error~.button { background: #c5391a; color: #fff; } .jCaptcha.success, .jCaptcha.success~.button { box-shadow: 0 0 8px #93a023; } .jCaptcha.success~.button { background: #b1c317; color: #fff; } .jCaptcha.disabled { background-color: #eff3f6; box-shadow: 0 0 8px #4e4706 !important; } .jCaptcha.disabled~.button { background: #e2e2e2; color: #7c7c7c; box-shadow: 0 0 8px #656565; cursor: not-allowed; } .button { padding: 21px 0; width: 150px; height: 60px; vertical-align: middle; box-sizing: border-box; font-size: 12px; font-weight: bold; background: #e8d639; cursor: pointer; border: none; color: #292b2b; line-height: 1; text-transform: uppercase; border-radius: 0 4px 4px 0; margin-left: -4px; letter-spacing: 0.5px; transition: all 150ms linear; box-shadow: 0 0 8px #4e4706; outline: none; } .button:hover, .button:focus { background: #e8d20b; } .codeBtn { display: inline-block; margin: 15px auto 0 auto; color: #ddd; font-size: 15px; padding: 12px; text-decoration: underline; cursor: pointer; } .btnWrap { bottom: 50px; left: 0; right: 0; position: absolute; } .jPopup .content { max-height: 82%; margin: 40px 10px 0 10px; text-align: center; color: #292b2b; font-family: "Courier New", Courier, "Lucida Sans Typewriter", "Lucida Typewriter", monospace; overflow: auto; } .jPopup .content strong { font-size: 30px; display: block; padding-bottom: 10px; } .jPopup .content p { font-size: 16px; text-align: left; display: inline-block; padding-bottom: 50px; white-space: nowrap; } .jPopup .content span { font-size: 16px; text-align: left; display: block; padding-bottom: 5px; color: #999; font-style: italic; } @media screen and (max-width: 540px) { h2 { font-size: 60px; } header p { padding-bottom: 7px; } main { position: static; left: auto; top: auto; width: 280px; margin: 100px auto 100px auto; height: auto; } .jCaptcha { width: 180px; height: 50px; padding: 15px 20px 15px 15px; } .btnWrap { position: static; left: auto; right: auto; bottom: auto; padding-bottom: 50px; } .button { width: 100px; height: 50px; padding: 16px 0; } .jPopup .content p, .jPopup .content span { font-size: 13px; } } </style> <body> <header> <h1>JavaScript Captcha</h1> <h2>jCaptcha</h2> <p>Tiny captcha component written in pure JavaScript with no dependencies based on canvas element</p> </header> <main> <form class="form" action=""> <input class="jCaptcha" type="text" placeholder="Type in result please"> <button class="button" type="submit">Submit</button> </form> <a class="codeBtn" role="button">View demo source code</a> </main> <footer class="btnWrap"> <a class="github-button" href="https://github.com/robiveli/js-captcha" data-size="large" aria-label="View on GitHub">View on GitHub</a> <a class="github-button" href="https://github.com/robiveli/js-captcha/archive/master.zip" data-icon="octicon-cloud-download" data-size="large" egaaria-label="Download robiveli/jCaptcha on GitHub">Download</a> </footer> <script src="js/index.min.js"></script> <!-- for demo purposes only --> <script src="https://www.rvdizajn.com/jpopup/js/jPopup.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/classlist/1.1.20170427/classList.min.js"></script> <!-- for demo purposes only --> <script> // optionally, set maximum number of captcha validation on event: const maxNumberOfTries = 5; // captcha initial setup var myCaptcha = new jCaptcha({ el: '.jCaptcha', canvasClass: 'jCaptchaCanvas', canvasStyle: { // properties for captcha stylings width: 100, height: 15, textBaseline: 'top', font: '15px Arial', textAlign: 'left', fillStyle: '#ddd' }, // set callback function callback: function (response, $captchaInputElement, numberOfTries) { if (maxNumberOfTries === numberOfTries) { // maximum attempts reached, so do something // e.g. disable the form: document.querySelector('form').removeEventListener('submit', formSubmit); $captchaInputElement.classList.add('disabled'); $captchaInputElement.placeholder = 'Maximum attempts reached!'; $captchaInputElement.setAttribute('disabled', 'true'); document.querySelector('button').setAttribute('disabled', 'true'); return; } if (response == 'success') { $captchaInputElement.classList.remove('error'); $captchaInputElement.classList.add('success'); $captchaInputElement.placeholder = 'Submit successful!'; // now continue with form submit } if (response == 'error') { $captchaInputElement.classList.remove('success'); $captchaInputElement.classList.add('error'); $captchaInputElement.placeholder = 'Please try again!'; } } }); function formSubmit(e) { e.preventDefault(); // myCaptcha validate myCaptcha.validate(); }; // validate captcha on form submit event document.querySelector('form').addEventListener('submit', formSubmit); // popup setup document.querySelector('.codeBtn').addEventListener('click', function () { var jPopupDemo = new jPopup({ content: '<strong>HTML</strong>\ <p>\ &lt;form class="form" action=""&gt;\ <br>\ &nbsp;&nbsp;&nbsp;&nbsp;&lt;input class="jCaptcha" type="text" placeholder="Type in result please"&gt;\ <br>\ &nbsp;&nbsp;&nbsp;&nbsp;&lt;button type="submit">Submit&lt;/button&gt;\ <br>\ &lt;/form&gt;\ </p>\ <strong>JavaScript</strong>\ <p>\ <span>// optionally, set maximum number of captcha validation on event:</span>\ const maxNumberOfTries = 5;\ <br>\ <br>\ <span>// captcha initial setup</span>\ var myCaptcha = new jCaptcha({\ <br><br>\ &nbsp;&nbsp;&nbsp;&nbsp;el: ".jCaptcha",\ <br>\ &nbsp;&nbsp;&nbsp;&nbsp;canvas: {\ <br>\ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class: "jCaptchaCanvas",\ <br>\ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;style: {\ <br>\ <span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// properties for captcha stylings:</span>\ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;width: 100,\ <br>\ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;height: 15,\ <br>\ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;textBaseline: "top",\ <br>\ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;font: "15px Arial",\ <br>\ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;textAlign: "left",\ <br>\ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fillStyle: "#ddd"\ <br>\ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}\ <br>\ &nbsp;&nbsp;&nbsp;&nbsp;},\ <br>\ <span>&nbsp;&nbsp;&nbsp;&nbsp;// set callback function</span>\ &nbsp;&nbsp;&nbsp;&nbsp;callback: function(response, $captchaInputElement, numberOfTries) {\ <br><br>\ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (maxNumberOfTries === numberOfTries) {\ <br><br>\ <span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// maximum attempts reached, so do something</span>\ <span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// e.g. disable the form:</span>\ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;document.querySelector("form").removeEventListener("submit", formSubmit);\ <br>\ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$captchaInputElement.classList.add("disabled");\ <br>\ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$captchaInputElement.placeholder = "Maximum attempts reached!"";\ <br>\ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$captchaInputElement.setAttribute("disabled", "true");\ <br>\ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;document.querySelector("button").setAttribute("disabled", "true");\ <br><br>\ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;\ <br>\ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}\ <br><br>\ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (response == \'success\') {\ <br><br>\ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$captchaInputElement[0].classList.remove(\'error\');\ <br>\ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$captchaInputElement[0].classList.add(\'success\');\ <br>\ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$captchaInputElement[0].placeholder = \'Submit successful!\';\ <br><br>\ <span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// continue with form submit</span>\ <br>\ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}\ <br><br>\ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (response == \'error\') {\ <br><br>\ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$captchaInputElement[0].classList.remove(\'success\');\ <br>\ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$captchaInputElement[0].classList.add(\'error\');\ <br>\ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$captchaInputElement[0].placeholder = \'Please try again!\';\ <br>\ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}\ <br>\ &nbsp;&nbsp;&nbsp;&nbsp;}\ <br><br>\ });\ <br><br>\ <span>// validate captcha on form submit event</span>\ function formSubmit(e) {\ <br>\ &nbsp;&nbsp;&nbsp;&nbsp;e.preventDefault();\ <br><br>\ <span>&nbsp;&nbsp;&nbsp;&nbsp;// myCaptcha validate</span>\ &nbsp;&nbsp;&nbsp;&nbsp;myCaptcha.validate();\ <br>\ };\ <br>\<br>\ document.querySelector("form").addEventListener("submit", formSubmit);\ <br><br>\ </p>' }); }); </script> </body> </html>