I have a simple form where one needs to enter a 4-digit PIN code. However, I would also like to autofill that PIN code when the user comes back to the website again, using JS cookies.
JS:
function loginCheck() { var pinCode = document.getElementById("pinCode").value; if (pinCode.match(/^[0-9]+$/) != null) { if (pinCode.length == 4) { function setCookie(cname, cvalue) { document.cookie = cname + "=" + cvalue + ";" } function getCookie(cname) { var name = cname + "="; var ca = document.cookie.split(';'); for(var i = 0; i < ca.length; i++) { var c = ca[i]; while (c.charAt(0) == ' ') { c = c.substring(1); } if (c.indexOf(name) == 0) { return c.substring(name.length, c.length); } } return ""; } function checkCookie() { var pinCode = document.getElementById("pinCode").value; var userPIN = getCookie("userPIN"); if (userPIN != "") { pinCode.value = userPIN; } else { setCookie("username", userPIN); } } checkCookie(); } else { document.getElementById("rightorwrong").innerHTML = "Not 4 digits!"; } } else { document.getElementById("rightorwrong").innerHTML = "Not a number!"; } }
HTML:
<div id = "validation"> <form id = "validationForm" target = "frame"> <fieldset> <label for = "pass">Password:</label><br /> <input type = "text" id = "pass" name = "pass" /><br /> <label for = "pinCode">4-digit PIN:</label><br /> <input type = "text" id = "pinCode" name = "pinCode" /><br /> <input type = "submit" value="Log In" onclick = "loginCheck()" /> </fieldset> </form> </div> <p id = "rightorwrong"></p>
I’m aware of a few things that are wrong about this code.
- in the
checkCookie()
function, if the user has a cookie stored, then I’m not entirely sure how to retrieve the PIN they first inputted. - Defining functions inside functions, and calling them by simply doing
checkCookie();
and nothing else, is generally bad practice. - When I run
checkCookie();
it only does the first part of theif
statement and not the second part. I’m not sure why and I couldn’t figure this out. - The code in general may have some errors. I modified a cookies script from here but it doesn’t seem to work.
I’m new to the idea of cookies, and am still trying to learn them. A step-by-step explanation would be more helpful.
Help would be greatly appreciated, TIA.
Advertisement
Answer
For cookies I use my “simpleCookie” object with the set / getVal methods to read or save a cookie.
ex:
simpleCookie.setVal( 'my cookie', 'ab/kjf;c', 3 ) let valueX = simpleCookie.getVal('my cookie')) // return 'ab/kjf;c' simpleCookie.setVal( 'my cookie', '', -1) remove the cookie
this object is achieved via an IIEF function, and I strongly advise you to use the mozilla documentation
Since automatic form validation exists, I no longer use a text box to indicate an input error, but I have diverted its “normal” use a bit because I find it very restrictive, as you will see in my code.
When at the base of your question, you just have to find a match between the name entered and a possible cookie with the same name, then save this cookie if the form is valid.
Oh, and I also put some css to simplify writing html (no more need for <br>
)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>login form</title> <style> fieldset { margin: 1em; width: 15em; } fieldset * { display: block; float: left; clear: both; margin-top: 0.2em; } fieldset label { margin-top: 0.7em; } fieldset button { margin-top: 2em; } fieldset button:last-of-type { clear: none; float: right; } </style> </head> <body> <form id="login-form" action=""> <fieldset> <label>Name:</label> <input type="text" name="name" autocomplete="off" pattern="[A-Za-z0-9]{1,20}"> <label>Password:</label> <input type="password" name="pass" pattern="[A-Za-z0-9]{1,20}"> <label>4-digit PIN:</label> <input type="text" name="pinCode" autocomplete="off" pattern="[0-9]{4}"> <button type="reset">clear</button> <button type="submit">Log In</button> </fieldset> </form> <script src="simpleCoolie.js"></script> <!-- the cookie object (IIFE) --> <script src="login_form.js"></script> </body> </html>
simpleCoolie.js :
// the cookie object (IIFE) const simpleCookie = (function() { const OneDay_ms = 24 *60 *60 *1000 // one Day in milliseconds return { setVal:(cName, cValue='', exDays=10)=> // 10 days is default cookie recovery, { // negative value remove the cookie cName = encodeURIComponent(cName.trim()) cValue = encodeURIComponent(cValue.trim()) if (cName) { let dte = new Date() dte.setTime(dte.getTime() + (exDays *OneDay_ms)) document.cookie = `${cName}=${cValue};expires=${dte.toUTCString()};SameSite=Strict;path=/` } } , getVal:cName=> { cName = encodeURIComponent(cName.trim()) let xCookie = document.cookie.split('; ').find(x=>x.startsWith(`${cName}=`)) return xCookie ? decodeURIComponent(xCookie.split('=')[1]) : '' } } })()
login_form.js :
const formLogin = document.getElementById('login-form') , msgErrorDuration = 5000 , checkInputs = [...formLogin.querySelectorAll('input[pattern]')] .map(el=> { let pattern = el.pattern el.removeAttribute('pattern') return { name:el.name, pattern } }); // generic set checking for report validyty const getCheckingValidity=(formElement, patternValue)=> { formElement.pattern = patternValue formElement.required = true return formElement.reportValidity() } // generic checking remove after delay const unCheckElement=(formElement,isOK)=> { formElement.removeAttribute('pattern') formElement.required = false if(!isOK) { formElement.setCustomValidity('') if(document.activeElement === formElement ) // bugg fix: Firefox doesnt remove error message after delay { // (other browser do) formElement.blur(); // double flip focus formElement.focus(); // --> will remove message bubble } } } // client-side form validation mecanism to get error message for each input formLogin.name.oninvalid=_=> { formLogin.name.setCustomValidity('Please enter a name') setTimeout(unCheckElement, msgErrorDuration, formLogin.name, false) } formLogin.pass.oninvalid=_=> { formLogin.pass.setCustomValidity("can't do anything without password !") setTimeout(unCheckElement, msgErrorDuration, formLogin.pass, false) } formLogin.pinCode.oninvalid=_=> { if (formLogin.pinCode.value==='') { formLogin.pinCode.setCustomValidity("PIN code can't be empty !") } else { formLogin.pinCode.setCustomValidity('PIN code must be 4 digits') } setTimeout(unCheckElement, msgErrorDuration, formLogin.pinCode, false) } formLogin.onsubmit=e=> { let validForm = true for (let Elm of checkInputs) { validForm = validForm && getCheckingValidity(formLogin[Elm.name], Elm.pattern ) if (validForm) { unCheckElement(formLogin[Elm.name], true) } else break } if (validForm) { simpleCookie.setVal( formLogin.name.value, formLogin.pinCode.value ) } else { e.preventDefault() } // disable form submiting } formLogin.name.oninput=()=> // check for cookie pin code on name { formLogin.pinCode.value = simpleCookie.getVal(formLogin.name.value) }
In 2009, session/localStorage arrived, which can replace cookies, especially for this kind of use.
To not have to redo all the previous logic, I created here a module called pseudoCookie which actually uses localStorage
here is the complete code to test with it:
// the pseudo cookie object (IIFE) const pseudoCookie = (function() // use localStorage { return { setVal:(cName, cValue='', exDays=10)=> // negative value remove the value in localstorage { // the values are kept until your browser or your system crashes cName = encodeURIComponent(cName.trim()) cValue = encodeURIComponent(cValue.trim()) if (cName) { if (exDays < 0) localStorage.removeItem(cName) else localStorage.setItem(cName, cValue) } } , getVal:cName=> { cName = encodeURIComponent(cName.trim()) let xCookie = localStorage.getItem(cName) return xCookie ? decodeURIComponent(xCookie) : '' } } })()
and the part to change in JS:
formLogin.onsubmit=e=> { let validForm = true for (let Elm of checkInputs) { validForm = validForm && getCheckingValidity(formLogin[Elm.name], Elm.pattern ) if (validForm) { unCheckElement(formLogin[Elm.name], true) } else break } if (validForm) { pseudoCookie.setVal( formLogin.name.value, formLogin.pinCode.value ) } else { e.preventDefault() } // disable form submiting } formLogin.name.oninput=()=> // check for cookie pin code on name { formLogin.pinCode.value = pseudoCookie.getVal(formLogin.name.value) }