-
Notifications
You must be signed in to change notification settings - Fork 0
[ ADD ON ] form validator
░░ VALIDATION FORMS
This script is useful for understanding how to validate a form (or more than one) in a page created with the framework.
Basically it is similar to any validator but it integrates perfectly with the available ui.
now ... it is not essential to understand everything but it is necessary to understand some key points:
-
the script cycles through all the forms
-
where it finds the "required" attribute enters and checks the values
-
if a pattern exists it will respect that pattern, otherwise it will assign a standard. If it does not exist ... it will not take into consideration the parameter. The control pattern can be given via the common html, the automatic one via a special "data-autopattern" attribute (it is true by default)
-
the most complicated is certainly the control on the dates... let's try to understand it. attributes are evaluated only if they exist.
You have several classes to put on the input field for more detailed checks: -
check[onlythisyear] -> check if the date is from the current year;
-
check[underage] -> check if the age is legally acceptable (here in Italy it is 18, in the USA it is 21 ... you can easily change it in the script)
-
check[dateprenotation] -> is the most advanced control. Check the standard, the min-max, and a range of enabling period.
- range of enabling period note: the period range is an addition. It is needed in those cases where there is the possibility, for example, to book only in a specific date range, leaving min and max to evaluate the daily range.
For example:
Range = "early summer, late summer"
Min and max = check if the day is antecendete or leave at least 24 hours before booking (or otherwise, it is up to you to edit the script)
In this regard there is an addition to the class of this validator that allows you to recover the current day and add or remove based on your needs. In this way you will be able to determine a minimum range of 24 hours (this day + 1) and the maximum general corrections.
- range of enabling period note: the period range is an addition. It is needed in those cases where there is the possibility, for example, to book only in a specific date range, leaving min and max to evaluate the daily range.
Important note: Being under construction some things may be missing or need to be removed. For example, the control on the radio buttons is not complete. Remember that.
to conclude: once the loop of the fields is finished, the script will estimate which are the main messages - without repeating them for each element - to bring to the user's attention. They will be printed in the appropriate element (you can configure its style like any other of the framework) which MUST BE IN THE FORM.
The script:
// k validator > https://git.io/JvQsK
class validator
{
constructor()
{
this.checkform();
}
checkform()
{
let Forms = document.getElementsByTagName('FORM');
if(Forms.length>=0)
{
let Fl = Forms.length;
for (let f = 0; f < Fl; f++)
{
// get elements nside that form
let FormElemets = Forms[f].querySelectorAll('[required]'),
send = Forms[f].querySelectorAll('[type="submit"]')[0],
alarmbox = Forms[f].querySelectorAll(Forms[f].tagName+' .alarmbox')[0],
alarmdisplay = alarmbox.querySelectorAll('.alarm-display')[0],
fields = [], // storized type of bad field (is it input text?)
alarmtext = {}, // storized message for bad field (if it's text and fields text exist... then write the message.)
isFormvalid = false;
if(FormElemets.length>=0)
{
// make required - add icon
let fel= FormElemets.length;
for (let i = 0; i < fel; i++)
{
let requirer = document.createElement('b');
requirer.classList.add('required');
FormElemets[i].parentNode.insertBefore(requirer, FormElemets[i]);
}
//activation
Forms[f].addEventListener("click", ()=>{ check(event); } );
//check it
function check(event)
{
// if exist, reset the list of fields
fields.length = 0;
// loop all "required" fields in form
let fel= FormElemets.length;
for (let i = 0; i < fel; i++)
{
// get the field
let El = FormElemets[i],
hasattribute,
pattern,
originalpattern,
textholder = El.getAttribute('placeholder'),
val = El.getAttribute('value'),
type = El.getAttribute('type'),
isvalid;
// some elements getted value from object and not attribute
val&&null!=val&&null!=val||(val=El.value);
// attribute exixst
if(El.hasAttribute('pattern') || El.hasAttribute('data-autopattern'))
{
hasattribute = true;
originalpattern = El.getAttribute('pattern');
pattern = new RegExp(originalpattern);
}
/// TEXT > check all inputs whit attribute "pattern":
if ( type == 'text' )
{
if(hasattribute)
{
if(!originalpattern)
{ pattern = new RegExp("^(?=.*[a-zA-Z0-9 ]).{3,25}$"); }
if(!pattern.test(val))
{ isvalid=false; alarmtext.text = 'error: you can only use simple letters, numbers and symbols in text fields.'; }
else
{ isvalid=true; }
}
else
{ if(!val || val == "" || val == textholder) isvalid=false; else isvalid= true; }
}
/// PASSWORD
else if( type == 'password' )
{
if(hasattribute)
{
if(!originalpattern)
{ pattern = new RegExp("^(?=.*[a-zA-Z0-9#$_^+=!*()@%&]).{8,12}$"); }
if(!pattern.test(val))
{ isvalid=false; alarmtext.password = 'error: incorrect characters on the password. 8-12 characters and at least one number and one symbol.'; }
else
{ isvalid=true; }
}
else
{ if(!val || val == "" || val == textholder) isvalid=false; else isvalid= true; }
}
/// NUMBER & TEL
else if ( type == 'number' || type == 'tel' )
{
if(hasattribute)
{
if(!originalpattern)
{ pattern =/^[0-9]+$/; }
if(!pattern.test(val))
{ isvalid=false; alarmtext.number = 'error: incorrect numeric fields.'; alarmtext.tel = 'error: incorrect phone fields.'; }
else
{ isvalid=true; }
}
else
{ if(!val || val == "" || val == textholder) isvalid=false; else isvalid= true; }
}
/// EMAIL
else if ( type == 'email' )
{
if(hasattribute)
{
if(!originalpattern)
{ pattern = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/; }
if( !pattern.test(val) || !val.match('@') && !val.match('.') )
{ isvalid=false; fields.email = false; alarmtext.email = 'error: incorrect email fields.'; }
else
{ isvalid=true; }
}
else
{ if(!val || val == "" || val == textholder) isvalid=false; else isvalid= true; }
}
/// URL
else if ( type == 'url' )
{
if(hasattribute)
{
if(!originalpattern)
{ pattern = new RegExp("^(http[s]?:\\/\\/(www\\.)?|ftp:\\/\\/(www\\.)?|www\\.){1}([0-9A-Za-z-\\.@:%_\+~#=]+)+((\\.[a-zA-Z]{2,3})+)(/(.)*)?(\\?(.)*)?") }
if(!pattern.test(val))
{ isvalid=false; alarmtext.url = 'error: you entered an invalid url.'; }
else
{ isvalid=true; }
}
else
{ if(!val || val == "" || val == textholder) isvalid=false; else isvalid= true; }
}
/// TEXTAREA
else if( El.tagName.toLowerCase() == 'textarea')
{
type = 'textarea';
if(hasattribute)
{
if(!originalpattern)
{ pattern = new RegExp("^(?=.*[a-zA-Z0-9#$_^+=!*()@%&<>/ ]).{10,350}$"); }
if(!pattern.test(val) || !val || val == textholder)
{ isvalid=false; alarmtext.textarea = 'error: description field wrong. 10 to 350 characters. Only letters, numbers and basic symbols.'; }
else
{ isvalid=true; }
}
else
{ if(!val || val == "" || val == textholder) isvalid=false; else isvalid= true; }
}
/// CHECKBOX
else if( type == 'checkbox' )
{
if(El.checked == false)
{ isvalid=false; alarmtext.checkbox = 'error: it seems that some ticks are incorrect or missing.'; }
else
{ isvalid=true; }
}
/// RADIO
else if( type == 'radio' )
{
if(El.checked == false)
{ isvalid=false; alarmtext.radiobox = 'error: it seems that some ticks are incorrect or missing.'; }
else
{ isvalid=true; }
// Under costruction
// che all name of radio, for all name...
// let Radios = E.closest('FORM').querySelectorAll()
// for (let i = 0; i < r.length; i++) {
// array[i]
// }
}
/// DATE
else if( type == 'date' )
{
let isunderagecheck; isunderagecheck=!!El.classList.contains("check[underage]"); // major people year
let isonlythisyear; isonlythisyear=!!El.classList.contains("check[onlythisyear]"); // only this year
let isprenotationcheck; isprenotationcheck=!!El.classList.contains("check[dateprenotation]"); // prenotation
let //get all type of variants data
date = new Date(), // init of date
thisyear = parseInt(date.getFullYear()), // get this yead
valToD = String(val.split("/")[2]), // day selected in the field
valToM = String(val.split("/")[1]), // months selected in the field
valToY = String(val.split("/")[0]), // year selected in the field
valDate = Date.parse( valToY+'/'+valToM+'/'+valToD ), // transormed utc data selected n the field
min = El.getAttribute('min'), // get min day date
max = El.getAttribute('max'), // get max day date
periodstart = null, // create a start of period range (or ex "start summer season": Date.parse(valToY+'/06/01') , alt: El.getAttribute('data-rangestart'))
periodend = null; // create a end of period range (or ex "start summer season": Date.parse(valToY+'/09/15') , alt: El.getAttribute('data-rangeend'))
// checks ege
if(isunderagecheck)
{
if(val == textholder )
{ isvalid = false; alarmtext.date = 'error on dates: missing date.'; }
else
{
let minimumEge = thisyear-18, //from this yead -18 = minimum day for major ege
overoldEge = thisyear-100; //are you dead?? :\
if(valToY>=minimumEge)
{ isvalid = false; alarmtext.date = 'error on dates: WARNING! You must be of age! Call your parents and get help.'; }
else if(valToY<=minimumEge && valToY<=overoldEge)
{ isvalid = false; alarmtext.date = 'error on dates: Are you over 100 years old? possible? Double check your dates!'; }
else
{ isvalid = true;}
}
}
else if( isonlythisyear && valToY != thisyear )
{ isvalid = false; alarmtext.date = "error on dates: Sorry, you can only book during the current year."; }
//check for complex prenotations
else if(isprenotationcheck)
{
if(val == textholder )
{ isvalid = false; alarmtext.date = 'error: missing date.'; }
else
{
if ( (periodstart != null && periodend != null) && (valDate < periodstart || valDate > periodend) )
{ isvalid = false; alarmtext.date = "error on dates: Sorry, only dates from "+ periodstart +" and "+ periodend +" are valid. All other dates are not available."; }
else
{
if( isonlythisyear && valToY != thisyear )
{ isvalid = false; alarmtext.date = "error on dates: Sorry, you can only book during the current year."; }
else
{
if( (min && max) && (valDate<min || valDate>max))
{ isvalid = false; alarmtext.date = 'error on dates: Too tight times! Please select a day longer than today.'; }
else
{
isvalid = true;
}
}
}
}
}
else
{
if(val == textholder )
{ isvalid = false; alarmtext.date = 'Error, missing date.'; }
else
{
if( (min && valDate<min) && (max && valDate>max))
{ isvalid = false; alarmtext.date = 'Tempi troppo stretti! Seleziona un giorno maggiore di quello di oggi.'; }
else
{
isvalid = true;
}
}
}
}
/// Select
else if(El.tagName.toLowerCase() == "select")
{
type = 'select';
val = El.parentNode.getElementsByTagName('p')[0].innerText;
if(val == textholder || El.getAttribute('value') ==textholder)
{ isvalid = false; alarmtext.select = 'error select: errors found in the selection and choice fields.'; }
else
{ isvalid = true; }
}
// set view result and array
if(isvalid==false)
{
fields.push({
type:type,
valy:isvalid,
message:alarmtext[type]
});
El.closest("[class*='button']").classList.remove('border-pass');
El.closest("[class*='button']").classList.add('border-error');
}
else if(isvalid==true)
{
fields.push({
type:type,
valy:isvalid,
message:''
});
El.closest("[class*='button']").classList.remove('border-error');
El.closest("[class*='button']").classList.add('border-pass');
}
// if loop ended
if(i==(fel-1))
{
//loop all field value. If even one is false, form is false!
isFormvalid = true;
for (let field in fields)
{
if(fields.hasOwnProperty(field))
{
if(fields[field].valy==false){isFormvalid=false;}
}
}
// print result and output:
if(isFormvalid == false)
{
event.stopPropagation();
send.closest("[class*='button']").classList.add('disabled','bkg-alert');
send.closest("[class*='button']").style.boxShadow="none";
send.closest("[class*='button']").disabled = true;
// loop all alarm label message and message in fileds, if that alarm label is present in the fields messages... print the alarm, else not.
let htmlcode = ``;
for (let alarm in alarmtext)
{
let keyexist=false;
for (let field in fields)
{
if(fields[field].message == alarmtext[alarm])
{
keyexist = true;
}
}
if(keyexist==true)
{
htmlcode += `<p>`+`${alarmtext[alarm]}`+`</p>`;
}
}
alarmdisplay.innerHTML=htmlcode;
alarmbox.classList.add('active');
alarmbox.classList.remove('off');
}
else
{
send.closest("[class*='button']").classList.remove('disabled','bkg-alert');
send.closest("[class*='button']").disabled = false;
alarmbox.classList.add('off');
alarmbox.classList.remove('active');
}
}
}
}
}
}
}
}
};
window.addEventListener("load", ()=>{
var formvalidator = new validator();
}, false);
exemple of html form:
<form>
<div class="button-text">
<input type="text" name="" value="" placeholder="this is a test" data-autopattern required/>
</div>
<div class="space-05"></div>
<div class="button-text">
<input type="email" name="" value="" placeholder="[email protected]" data-autopattern required/>
</div>
<div class="space-05"></div>
<div class="button-text">
<input type="password" name="" value="" placeholder="password" data-autopattern required/>
</div>
<div class="space-05"></div>
<div class="button-text">
<input type="url" placeholder="www.yoursite.com" data-autopattern required/>
</div>
<div class="space-05"></div>
<div class="button-text">
<input type="tel" placeholder="00000000000" data-autopattern required/>
</div>
<div class="space-05"></div>
<div class="button-text">
<textarea placeholder="a simple textarea" data-autopattern required>a simple textarea</textarea>
</div>
<div class="space-05"></div>
<p class="font-size-8-tone-2">classic check</p>
<div class="button-date EUR DMY">
<p>Calendar...</p>
<input type="date" value="Calendar..." placeholder="Calendar..." required/>
</div>
<div class="space-05"></div>
<p class="font-size-8-tone-2">check only this year</p>
<div class="button-date EUR DMY">
<p>select a date</p>
<input class="check[onlythisyear]" type="date" value="select a date" placeholder="select a date" required/>
</div>
<div class="space-05"></div>
<p class="font-size-8-tone-2">check under age</p>
<div class="button-date EUR DMY">
<p>Your age</p>
<input class="check[underage]" type="date" value="Your age" placeholder="Your age" required/>
</div>
<div class="space-05"></div>
<p class="font-size-8-tone-2">prenotation check</p>
<div class="button-group">
<div class="button-date EUR DMY ">
<p>From...</p>
<input class="check[dateprenotation]" type="date" value="From..." placeholder="From..." required/>
</div>
<div class="button-date EUR DMY prenotation">
<p>To...</p>
<input class="check[dateprenotation]" type="date" value="To..." placeholder="To..." required/>
</div>
</div>
<div class="space-05"></div>
<div class="button-number">
<span> <p>-</p> <span>
<span> <p>+</p> <span>
<div></div>
<input type="number" min="-100" max="100" value="0" readonly required/>
</div>
<div class="space-10"></div>
<div class="alarmbox off">
<div class="alarm-display bkg-alert radius-small font-small font-tone-1 space-15 align-left">
</div>
<div class="space-10"></div>
</div>
<div class="button-action">
<input type="submit" name="" value="TRY NOW"/>
</div>
</form>
As mentioned above, when checking dates, it will often be necessary to change the min and max for a short-term check.
The problem is that, having reached this level, it is necessary to do it dynamically.
"What day is it? Add 1 to give customers time to get organized"
or:
"What day is it? Is it before today? Then you can't!"
How to do? We built an expansion of the validator. addition to the previous script (before that of the validator!)
Here is the addition:
class validator
{
constructor()
{
this.getMinMaxDay();
this.checkform();
}
getMinMaxDay()
{
let El = [...document.querySelectorAll('input[type="date"]')],
elfinded = El.length,
todayDate = new Date(),
thisyear = todayDate.getFullYear();
for (let i = 0; i < elfinded; i++)
{
let attrs = El[i].attributes,
attrsleng = attrs.length;
for (let i = 0; i < attrsleng; i++)
{
let attr = attrs[i];
if(attr.value=='getMinDay')
{
// original
// let dd = String(todayDate.getDate()+1).padStart(2, '0'),
// mm = String(todayDate.getMonth()).padStart(2, '0'),
// tomorrow = Date.parse(thisyear+'/'+mm+'/'+dd);
let dd = String(todayDate.getDate()+1).padStart(2, '0'),
mm = String(todayDate.getMonth()).padStart(2, '0');
if(parseInt(mm)<4){ mm="04"; dd="01"; }
else if(parseInt(mm)>9){ mm="09"; dd="14"; }
let tomorrow = Date.parse(thisyear+'/'+mm+'/'+dd);
attr.value = tomorrow;
}
else if(attr.value=='getMaxDay')
{
let summerclose = Date.parse(thisyear+'/09/14'); // in this app summer end to september
attr.value = summerclose;
}
}
}
}
checkform()
{
...
}
how to set the html:
<form>
<div class="button-date EUR DMY">
<p>Calendar...</p>
<input type="date" value="Calendar..." min="getMinDay" max="getMaxDay"/>
</div>
</form>
Before all:
- HOME
- INTRODUCTION
- WHAT'S NEW
How to:
- INSTALL
- VIEWS TYPES
- BASIC CONCEPTS
- LOADER & LAZY
- CLASSES
- UI ASSET
- FILE LOADER
- DRAG & DROP
- EFFECTOR
- THEME
addons:
- Form validator model
utility:
- roadmap
- release
- issue
- comunication