Skip to content

Commit

Permalink
Update:
Browse files Browse the repository at this point in the history
- Added Error count per form:
    - Form can now be checked if error exists and form submission prevented.
  • Loading branch information
Bien-Glitch committed Sep 8, 2021
1 parent 81d982b commit a90f8ec
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 325 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
---

## Installation
[jQuery](https://github.com/jquery/jquery/releases/latest) 3.x, [Bootstrap](https://getbootstrap.com/docs/5.0/getting-started/download/) 5.x, and [Fontawesome]() 6.x are required.
[jQuery](https://github.com/jquery/jquery/releases/latest) 3.x, [Bootstrap](https://getbootstrap.com/docs/5.0/getting-started/download/) 5.x, and [Fontawesome](https://fontawesome.com/v6.0) 6.x are required.

No worries, the above requirements are shipped along with the Fusion Form Validator package.\
To get the latest version of Fusion Form Validator, simply head over to [Github](https://github.com/Bien-Glitch/fusion.form.validator/releases/latest) and download the assets.
Expand Down
14 changes: 14 additions & 0 deletions src/example/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,20 @@
<div class="text-center my-1"><a type="button">Don't have an account ?</a></div>
</div>
</form>

<form action="" method="POST" class="d-block w3-light-grey rounded-3 shadow-sm m-auto px-4 pt-4 py-2" id="valid-form2">
<div class="form-group">
<div class="input-group input-group-sm align-items-center flex-nowrap">
<i class="far fa-1x fa-phone-alt pe-2"></i>
<div class="form-label-group form-label-group-sm required w-100">
<!--<div class="bfh-selectbox bfh-countries" data-country="NG" data-blank="false" data-flags="true"></div>-->
<input type="text" minlength="9" maxlength="19" name="phone" id="phone2" class="form-control form-control-sm bfh-phone" data-country="NG" placeholder="Phone Number">
<label for="phone2" class="col-form-label-sm">Phone Number</label>
</div>
</div>
<div id="phone2Valid" class="w3-small valid-text"></div>
</div>
</form>
</div>
</body>

Expand Down
141 changes: 93 additions & 48 deletions src/js/fb-formvalidator/fusion.form.validator.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
* Copyright 2021 Fusion Bolt inc.
*/

// TODO: form.validation.js to be deprecated in next version
// TODO: Add option for strict validation. (i.e Restrict form submission if there are validation errors)

/**
Expand Down Expand Up @@ -35,19 +34,8 @@ let valid_right,
valid: '<i class="fa far fa-1x fa-check"></i>',
}
},

paddingMultipliers = {
input: '2.5',
input$sm: '3.5',
select: '4',
select$sm: '5.8',
validDate: '3',
validDate$sm: '3.8',
validInput: '0.9',
validInput$sm: '3 / 2',
validSelect: '3',
validSelect$sm: '3.8',
};
paddingMultipliers = [];


/**
* ----------------------------------------------------------
Expand Down Expand Up @@ -83,14 +71,31 @@ class Base {
constructor(element, form) {
this._form = form;
this._element = element;
this.#_config = default_validator_config;
this.#_config = {
regExp: {
email: /^\w+([.-]?\w+)*@\w+([.-]?\w{2,3})*(\.\w{2,3})$/gi,
phone: /^(\+\d{1,3}?\s)(\(\d{3}\)\s)?(\d+\s)*(\d{2,3}-?\d+)+$/g,
},
validation: {
nativeValidation: false,
passwordId: 'password',
passwordConfirmId: 'password_confirmation',
validateEmail: false,
validatePhone: false,
validatePassword: false,
},
validation_icons: {
invalid: '<i class="fa far fa-1x fa-exclamation-circle"></i>',
valid: '<i class="fa far fa-1x fa-check"></i>',
}
};

this.#_invalidWrapper = (icon) => {
return '<small class="position-absolute text-danger invalid validation-icon">' + icon + '</small>';
return `<small class="position-absolute text-danger invalid validation-icon">${icon}</small>`;
}

this.#_validWrapper = (icon) => {
return '<small class="position-absolute text-success valid validation-icon">' + icon + '</small>';
return `<small class="position-absolute text-success valid validation-icon">${icon}</small>`;
}
}

Expand All @@ -114,13 +119,15 @@ class Base {
return this.#_validWrapper
}


/** Setters **/

/* * *Assign the base element* * */
set baseElement(element) {
this._element = element;
}


/** Static **/

/* * *Get current validator version* * */
Expand Down Expand Up @@ -148,7 +155,18 @@ class ValidateForm extends Base {
let _config = this.config;

this.#_regExp = _config.regExp;
this.#_padding = paddingMultipliers;
this.#_padding = {
input: 2.5,
input$sm: 3.5,
select: 4,
select$sm: 5.8,
validDate: 3,
validDate$sm: 3.8,
validInput: 0.9,
validInput$sm: 1.5,
validSelect: 3,
validSelect$sm: 3.8,
};
this.#_validation = _config.validation;
this.#_validation_icons = _config.validation_icons;
this.#_invalid = this.invalidIcon;
Expand All @@ -170,23 +188,25 @@ class ValidateForm extends Base {
validation = this.#_validation,
icons = this.#_validation_icons,
invalidWrapper = this.#_invalid,
validWrapper = this.#_valid;
/*padding = this._padding*/
validWrapper = this.#_valid,
context = `#${form.id} ${this._element}`;
paddingMultipliers[form.id] = this.#_padding;
errorBag[form.id] = {};
errorCount[form.id] = 0;

if (validation.nativeValidation)
$(form).removeAttr('novalidate');
else
$(form).attr({novalidate: ''});


$(this._element).each(function () {
$(context).each(function () {
let target = this,
element = $('input, textarea, select', target),
inputElement = $('input, textarea', target),
selectElement = $('select', target),
element_id = $(element).attr('id');

$(target).attr('id', element_id + '_group');
$(target).attr('id', `${element_id}_group`);
$('.input-group', target).append(validWrapper(icons.valid)).append(invalidWrapper(icons.invalid));

inputElement.on({
Expand All @@ -198,8 +218,8 @@ class ValidateForm extends Base {
inputElement.validate(target);
else {
if (_type === 'password' && validation.validatePassword) {
let _password_id = '#' + validation.passwordId,
_password_confirm_id = '#' + validation.passwordConfirmId,
let _password_id = `#${validation.passwordId}`,
_password_confirm_id = `#${validation.passwordConfirmId}`,
_password = $(_password_id),
_password_confirm = $(_password_confirm_id),
minlength = _password.attr('minlength'),
Expand All @@ -209,7 +229,7 @@ class ValidateForm extends Base {
if (inputElement.val().length < minlength || inputElement.val().length > maxlength) {
if ($(form).has(_password_confirm).length)
_password_confirm.validate(_password_confirm.parents(form_group), null, true);
inputElement.validate(target, 'Password must be between ' + minlength + ' and ' + maxlength + ' characters');
inputElement.validate(target, `Password must be between ${minlength} and ${maxlength} characters`);
} else {
if ($(form).has(_password_confirm).length)
if ((inputElement.val().length > 0 && _password_confirm.val().length > 0) && inputElement.val() !== _password_confirm.val()) {
Expand All @@ -228,7 +248,7 @@ class ValidateForm extends Base {
else {
if (_password.val().length < minlength || _password.val().length > maxlength) {
inputElement.validate(target, null, true);
_password.validate(_password.parents(form_group), 'Password must be between ' + minlength + ' and ' + maxlength + ' characters');
_password.validate(_password.parents(form_group), `Password must be between ${minlength} and ${maxlength} characters'`);
} else if (inputElement.val().length < 1)
inputElement.validate(target)
else if (inputElement.val() !== _password.val()) {
Expand Down Expand Up @@ -265,9 +285,10 @@ class ValidateForm extends Base {
});

selectElement.on('change', function () {
toggleValidation(target);
})
$(this).validate(target);
});
});

return this;
}

Expand Down Expand Up @@ -345,7 +366,7 @@ class ValidateForm extends Base {
* @returns {string}
*/
function multiplyPadding(pad1, pad2) {
return 'calc(' + pad1 + ' * ' + pad2 + ')';
return `calc(${pad1} * ${pad2})`;
}

/**
Expand All @@ -361,6 +382,9 @@ function onAlertClose(context) {
});
}

errorBag = {};
errorCount = {};

jQuery.fn.extend({
/**
* Create a new instance of Fusion Form Validator
Expand Down Expand Up @@ -394,6 +418,19 @@ jQuery.fn.extend({
let _target_id = $(this[0]).attr('id')
return _target_id.match(/phone/gi);
},
/**
* Checks if a form element has any validation (* When using Fusion Form Validator *) errors
* @returns {Error|boolean}
*/
hasErrors() {
let _target = this[0];

if (_target.tagName.toLowerCase() === 'form')
return errorCount[_target.id] > 0;

console.error(`Expected 'form element' but '${_target.tagName.toLowerCase()} element' given`);
return new Error(`Function hasErrors() accepts only 'form element', '${_target.tagName.toLowerCase()} element' given!`);
},
/**
* Close specified Validation alert
* @param context
Expand All @@ -402,25 +439,29 @@ jQuery.fn.extend({
removeValidationText(context, close = false) {
let _target = this[0],
e = $(_target).validationProps();
delete errorBag[_target.form.id][_target.id];
errorCount[_target.form.id] = Object.keys(errorBag[_target.form.id]).length;

if (close)
$(e.validField + ' > .alert', context).alert('close');
$(`${e.validField} > .alert`, context).alert('close');

$(_target).removeClass('border-danger').removeClass('border-success');
$(e.validationIcon).fadeOut();
$(_target).removeValidPad();

return _target;
},
validationProps() {
let target = this[0],
target_id = $(target).attr('id'),
_target_id = '#' + target_id
target_id = target.id,
_target_id = `#${target_id}`;

return {
id: _target_id,
validField: $(_target_id + 'Valid'),
validIcon: $(form_group + _target_id + '_group ' + input_group + ' > .valid'),
invalidIcon: $(form_group + _target_id + '_group ' + input_group + ' > .invalid'),
validationIcon: $(form_group + _target_id + '_group ' + input_group + ' > .validation-icon')
validField: $(`${_target_id}Valid`),
validIcon: $(form_group + `${_target_id}_group ${input_group} > .valid`),
invalidIcon: $(form_group + `${_target_id}_group ${input_group} > .invalid`),
validationIcon: $(form_group + `${_target_id}_group ${input_group} > .validation-icon`)
}
},
/**
Expand Down Expand Up @@ -464,6 +505,7 @@ jQuery.fn.extend({
addValidText(context, message, icon = true) {
let _target = this[0],
e = $(_target).validationProps();
delete errorBag[_target.form.id][_target.id];

if (icon) {
e.invalidIcon.fadeOut(0);
Expand All @@ -482,6 +524,7 @@ jQuery.fn.extend({
let _target = this[0],
_message = !message ? 'This field is required' : message,
e = $(_target).validationProps();
errorBag[_target.form.id][_target.id] = true;

if (icon) {
e.validIcon.fadeOut(0);
Expand All @@ -498,30 +541,30 @@ jQuery.fn.extend({
},
displayMessage(bs_alert, fa_icon, message, id, context = null, dismissible = false, wait = false) {
let message_tag = this[0],
_bs_alert = dismissible ? bs_alert + ' alert-dismissible' : bs_alert,
_bs_alert = dismissible ? `${bs_alert} alert-dismissible` : bs_alert,
_message_tag = context ? $(message_tag, context) : $(message_tag),
_dismiss = dismissible ? '<a type="button" class="text-danger" data-bs-dismiss="alert"><i class="fa fa-times-circle"></i></a>' : '',
_wait = wait ? '<br><i class="fa fa-1x fa-spin fa-spinner-third"></i> Please Wait...' : '';

_message_tag.html('\
<div class="alert ' + _bs_alert + ' d-flex justify-content-between align-items-center pr-0 p-1 mt-1 fade show" data-alert-id="' + id + '" role="alert">\n\
_message_tag.html(`\
<div class="alert ${_bs_alert} d-flex justify-content-between align-items-center pr-0 p-1 mt-1 fade show" data-alert-id="${id}" role="alert">\n\
<div class="px-1">\n\
<i class="fa far fa-1x ' + fa_icon + '"></i>\n\
<span>' + message + '</span>\n\
' + _wait + '\n\
<i class="fa far fa-1x ${fa_icon}"></i>\n\
<span>${message}</span>\n\
${_wait}\n\
</div>\n\
' + _dismiss + '\n\
${_dismiss}\n\
</div>\
');
`);
return this;
},
validate(context, message, password = false, errors = false) {
let _target = this[0],
_pad = paddingMultipliers,
_pad = paddingMultipliers[_target.form.id],
_type = ($(_target).attr('type') ?? '').toLowerCase(),
_padding_x = $(_target).css('padding-left'),
_min_input_length = (_target.tagName.toLowerCase() !== 'select' ? $(_target).attr('minlength') : false),
_message = (_min_input_length ? (($(_target).val().length < _min_input_length && !message) ? 'This field requires a minimum of ' + _min_input_length + ' characters' : message) : message);
_message = (_min_input_length ? (($(_target).val().length < _min_input_length && !message) ? `This field requires a minimum of ${_min_input_length} characters` : message) : message);

if (_type === 'date' || _type === 'datetime' || _type === 'datetime-local')
valid_right = $(_target).hasClass('form-control-sm') ? multiplyPadding(_padding_x, _pad.validDate$sm) : multiplyPadding(_padding_x, _pad.validDate);
Expand All @@ -535,11 +578,13 @@ jQuery.fn.extend({
}
}

if ($((_target.tagName.toLowerCase() !== 'select') ? _target : _target + ' > option:selected').val().length < 1 || $(_target).val().length < _min_input_length || password || errors)
if ($((_target.tagName.toLowerCase() !== 'select') ? _target : `${_target} > option:selected`).val().length < 1 || $(_target).val().length < _min_input_length || password || errors)
$(_target).addInvalidText(context, _message);
else
$(_target).addValidText(context);
errorCount[_target.form.id] = Object.keys(errorBag[_target.form.id]).length;
onAlertClose();

return this;
},
});
Expand Down
31 changes: 24 additions & 7 deletions src/js/fb-formvalidator/init.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,26 @@
/*console.log(ValidateForm.VERSION);
console.log(window.fusion.default_validator_config);*/
// Assign initialised validators to variables
let form = '#valid-form',
form_validator = $(form).fusionFormValidator(form_group),
form_v = $('#valid-form2').fusionFormValidator(form_group);

/*$('form').fusionFormValidator(form_group).validateForm();*/
/*document.querySelectorAll('form').forEach((val) => {
new ValidateForm(form_group, val).validateForm();
});*/
// Change padding for validation Icon in the second form
form_v.padding_config = {validInput$sm: 6};
form_validator.validation_config = {validateEmail: true};

new ValidateForm(form_group, document.getElementById('valid-form')).validateForm();
// Call the 'validateForm()' method
form_v.validateForm();
form_validator.validateForm();

$(form).on('submit', function (e) {
e.preventDefault();

if (!$(this).hasErrors())
$(this).off('submit').submit();
else
alert('Cannot submit form while there are errors!!!');
});

/*
console.log(ValidateForm.VERSION);
console.log(form.padding_multipliers);
console.log(form_v.padding_multipliers);*/
Loading

0 comments on commit a90f8ec

Please sign in to comment.