Last active
August 12, 2020 11:45
-
-
Save TsubasaKawajiri/f3fbd029119de87c208535bc1c0cca2b to your computer and use it in GitHub Desktop.
JavaScript versatile Form Validator. inspired ActiveModelValidations
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import ValidatorsFactory from '../validators/ValidatorsFactory' | |
const pagename = /* get pagename */ | |
const factory = new ValidatorsFactory(pageName) | |
const validators = factory.createValidators() | |
if (validators === null) { | |
return | |
} | |
validators.bindSubmitButton() | |
validators.forEach((validator) => { | |
validator.bind() | |
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export default class AbstractValidator { | |
bind(){} | |
_validate(){} | |
backgroundValidate(){ | |
this._resetError() | |
this._validate() | |
} | |
foregroundValidate(){ | |
this._resetError() | |
this._hideError() | |
this._validate() | |
if (this.hasError()) { | |
this._showError() | |
} | |
} | |
hasError(){} | |
_showError(){} | |
_hideError(){} | |
_resetError(){} | |
_buildErrorHTML(){} | |
_presence(){} | |
_maxLength(){} | |
_minLength(){} | |
_betweenLength(){} | |
_regex(){} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export class TextValidator extends AbstractValidator { | |
constructor(target){ | |
super() | |
// input name. example: last_name | |
this.name = target.name | |
this.input = target.input | |
this.validation = target.validation | |
this.error = '' | |
} | |
bind(){ | |
this.input.blur(() => { | |
this.foregroundValidate() | |
}) | |
} | |
hasError(){ | |
return this.error != '' | |
} | |
_validate(){ | |
this.val = this.getValue() | |
this._presence() | |
if (this.validation.betweenLength) { | |
this._betweenLength() | |
} else { | |
this._minLength() | |
this._maxLength() | |
} | |
this._regex() | |
} | |
_showError(){ | |
this.input.parent.append(this._buildErrorHTML(this.error)) | |
} | |
_hideError(){ | |
this.input.parent.children('.error').remove() | |
} | |
_resetError(){ | |
this.error = '' | |
} | |
_buildErrorHTML(error){ | |
return `<span class='error'>${error}</span>` | |
} | |
// validations | |
_presence(){ | |
if (!this.validation.presence) { | |
return | |
} | |
if(this.presenceCondition()){ | |
this.error = this.presenceErrorText() | |
} | |
} | |
_minLength(){ | |
if (this.validation.minLength < 0 || this.error) { | |
return | |
} | |
if(this.val.length < this.validation.minLength){ | |
this.error = this.minLengthErrorText() | |
} | |
} | |
_maxLength(){ | |
if (this.validation.maxLength <= 0 || this.error) { | |
return | |
} | |
if(this.val.length > this.validation.maxLength){ | |
this.error = this.maxLengthErrorText() | |
} | |
} | |
_betweenLength(){ | |
if (this.validation.minLength <= 0 || 0 >= this.validation.maxLength && this.error) { | |
return | |
} | |
if (this.val.length < this.validation.minLength || this.validation.maxLength < this.val.length) { | |
this.error = this.betweenLengthErrorText() | |
} | |
} | |
_regex(){ | |
if (!this.validation.regex || this.error) { | |
return | |
} | |
if (!this.val.match(this.validation.regex)) { | |
this.error = this.validation.regexErrorText | |
} | |
} | |
// for extends | |
/** | |
* @return {value} InputValue | |
*/ | |
getValue(){ | |
return this.input.val() | |
} | |
/** | |
* @return {boolean} | |
*/ | |
presenceCondition(){ | |
return this.val === '' || this.val === undefined || this.val === null | |
} | |
/** | |
* @return {string} | |
*/ | |
presenceErrorText(){ | |
return `${this.name ? this.name + 'is' : ''} must input` | |
} | |
/** | |
* @return {string} | |
*/ | |
minLengthErrorText(){ | |
return `${this.name ? this.name + 'is' : ''} must more than ${this.validation.minLength}` | |
} | |
/** | |
* @return {string} | |
*/ | |
maxLengthErrorText(){ | |
return `${this.name ? this.name + 'is' : ''} must less than ${this.validation.maxLength}` | |
} | |
/** | |
* @return {string} | |
*/ | |
betweenLengthErrorText(){ | |
return `${this.name ? this.name + 'is' : ''} between more than${this.validation.minLength} and less than ${this.validation.maxLength}` | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const ValidationTargets = { | |
sample: [ | |
{ | |
name: 'mail_address', input: /* input element */, | |
validation:{ | |
presence: true, maxLength: 100, | |
regex: /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(?!\.).@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*/, | |
regexErrorText: 'invalid', | |
}, type: 'text' | |
}, | |
{ | |
name: 'last_name', form: /* input element */, | |
validation: { presence: true, maxLength: 30 }, type: 'text' | |
} | |
] | |
} | |
export default ValidationTargets |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export class Validators { | |
constructor(form){ | |
this.validators = [] | |
this.form = form | |
} | |
bindSubmitButton(){ | |
let isSubmitting = false | |
this.form.submit(() => { | |
if(isSubmitting) { | |
return false | |
} | |
if(this._canSubmit()) { | |
isSubmitting = true | |
return true | |
} | |
}) | |
} | |
push(validator){ | |
this.validators.push(validator) | |
} | |
forEach(callback){ | |
return this.validators.forEach(callback) | |
} | |
filter(callback){ | |
return this.validators.filter(callback) | |
} | |
_canSubmit(){ | |
this.validators.forEach(validator => { | |
validator.foregroundValidate() | |
}) | |
return this.validators.every((validator => { | |
return !validator.hasError() | |
})) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import ValidationTargets from './ValidationTargets' | |
import TextValidator from './Validator' | |
export default class ValidatorsFactory { | |
constructor(pageName){ | |
this.pageName = pageName | |
} | |
createValidators(){ | |
const validators = new Validators() | |
ValidationTargets[this.pageName].forEach((target) => { | |
validators.push(this._validator(target)) | |
}) | |
return validators | |
} | |
_validator(target){ | |
if (target.type === 'text') { | |
return new TextValidator(target) | |
} | |
// Example Sample | |
// if(target.type === 'password') { | |
// return new PasswordValidator(target) | |
// } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment