Skip to content

Instantly share code, notes, and snippets.

@r1cebank
Last active August 14, 2017 17:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save r1cebank/5f937a8412d7cfdc6ff597b6db6daccb to your computer and use it in GitHub Desktop.
Save r1cebank/5f937a8412d7cfdc6ff597b6db6daccb to your computer and use it in GitHub Desktop.
chanable js - input validator
import isEmpty from 'lodash/isEmpty';
import validators from '../validators';
import noop from '../utils/noop.js';
function addProperty (context, name, getter) {
if (typeof getter !== 'function') { getter = function() { }; }
Object.defineProperty(context, name, {
get() {
const result = getter.call(this);
return result === undefined ? this : result;
}
});
}
const conjunctions = [ 'to', 'be', 'been', 'is', 'that', 'which', 'and', 'has', 'have',
'with', 'at', 'same', 'in', 'a', 'an', 'the' ];
function clearClass (element) {
element.element.removeClass(element.classes.onSuccess);
element.element.removeClass(element.classes.onFailure);
}
class Element {
constructor (element) {
if (!(element instanceof jQuery)) {
throw new Error('Not a valid jQuery element');
}
this.element = element;
this.type = 'any';
this.classes = {
onSuccess: '',
onFailure: ''
}
this.lastValidationResult = false;
this.failureType = 'required';
this.sameAsSelector = '';
this.isRequired = false;
this.events = [];
this.customValidator = noop;
this.usingCustom = false;
this.handlers = {
onSuccess: noop,
onFailure: noop,
onFinish: noop
};
conjunctions.forEach((item) => {
addProperty(this, item);
});
}
applyClass (onSuccess = '', onFailure = '') {
this.classes.onSuccess = onSuccess;
this.classes.onFailure = onFailure;
return this;
}
sameAs(selector) {
this.sameAsSelector = selector;
return this;
}
valueOf (type) {
if (typeof validators[type] !== 'function') {
throw new Error('Validator type invalid!');
}
this.type = type;
return this;
}
group (group) {
this.group = group;
return this;
}
success (handler) {
this.handlers.onSuccess = handler;
return this;
}
fail (handler) {
this.handlers.onFailure = handler;
return this;
}
finish (handler) {
this.handlers.onFinish = handler;
return this;
}
required (required) {
if (!required) {
this.lastValidationResult = true;
}
this.isRequired = !!required;
return this;
}
finish (handler) {
this.customValidator = handler;
this.usingCustom = true;
return this;
}
on (event) {
this.events.push(event);
this.element.on(event, (event) => {
this.validate();
if (this.lastValidationResult) {
clearClass(this);
if (isEmpty(this.element.val()) && !this.isRequired) {
this.optionalClear = true;
}
this.element.addClass(this.classes.onSuccess);
this.handlers.onSuccess(this);
} else {
clearClass(this);
this.element.addClass(this.classes.onFailure);
this.handlers.onFailure(this);
}
this.handlers.onFinish(this);
});
return this;
}
validate () {
const validator = this.usingCustom ? this.customValidator.bind(this) : validators[this.type];
const elementValue = this.element.val();
const valueEmpty = isEmpty(elementValue);
this.lastValidationResult = validator(elementValue, this);
if (this.isRequired && valueEmpty) {
this.failureType = 'required';
this.lastValidationResult = false;
} else {
this.failureType = 'invalid';
}
if (!this.isRequired && valueEmpty) {
this.lastValidationResult = true;
}
return this;
}
detach () {
if (this.element instanceof jQuery) {
this.events.map((event) => {
this.element.unbind(event);
});
}
return this;
}
};
// Usage
const expectElement = Expect(element).to.have.valueOf('any').with
.customValidator(validate).success(onSuccess).fail(onFailure).on(event).with.group(group);
module.exports = Element;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment