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)
}