Skip to content

Instantly share code, notes, and snippets.

@ksprwhite
Last active February 26, 2018 23:28
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ksprwhite/f764a22cfb6758c7f9c4 to your computer and use it in GitHub Desktop.
Save ksprwhite/f764a22cfb6758c7f9c4 to your computer and use it in GitHub Desktop.
bootstrap validation | nav-tabs
var FormValidation = (function($) {
var context = null;
function FormValidation(form) {
this.form = $(form);
this.tabs = $(form).find('.nav-tabs a[role="tab"]');
this.panels = $(form).find('.tab-content [role="tabpanel"]');
context = this.init();
}
FormValidation.prototype = $.extend({
steps: 0,
step: 1,
cache: {
inputs: {},
validSteps: {}
},
completed: false,
init: function() {
// get total steps
this.steps = this.tabs.length;
if (this.panels.length !== this.tabs.length) {
throw new Error('tabs must have same amount of panels');
}
// disable submit, enable next and finish
this.form.submit(function() {
context.tabs.eq(context.step).tab('show');
if (context.step == context.steps && context.checkStep(context.steps)) {
context.cache.validSteps[context.steps] = true;
}
return context.completed;
});
this.form.find('.form-footer .finish').on('click', function() {
context.completed = context.complete();
console.log(context.completed);
});
// enable step 1
this.tabs.first().tab('show');
// bind click on tab change
this.tabs.on('show.bs.tab', function(e) {
var previousStep = $(e.relatedTarget).parent('li').index() + 1,
currentStep = $(e.target).parent('li').index() + 1;
if (context.checkStep(previousStep)) {
context.cache.validSteps[previousStep] = true;
context.step = currentStep;
} else
return false;
if (currentStep == context.steps) {
context.form.find('.form-footer .next').hide();
context.form.find('.form-footer .finish').show();
} else {
context.form.find('.form-footer .finish').hide();
context.form.find('.form-footer .next').show();
}
});
this.tabs.on('shown.bs.tab', function(e) {
context.form.find('.popover').popover('show');
});
return this;
},
complete: function() {
var inputs = this.cache.inputs,
valid = true;
$.each(inputs, function(name, data) {
context.checkInput(data.input, true)
});
$.each(inputs, function(name, data) {
if (!context.checkInput(data.input, true)) {
context.step = data.step - 1;
context.tabs.eq(data.step - 1).tab('show');
valid = false;
return false;
}
});
return valid;
},
checkStep: function(step) {
var valid = true,
tab_id = '#' + this.tabs.eq(step - 1).attr('aria-controls'),
inputs = $(tab_id).find('input, select');
inputs.each(function() {
context.cache.inputs[$(this).attr('name')] = {
input: this,
value: $(this).val(),
step: step
};
if (!context.checkInput(this)) {
valid = false
}
});
return valid;
},
checkInput: function(input) {
var name = $(input).attr('name'),
value = $(input).val();
if ($.trim(value) == '')
return this.helper.apply(input, ['Este campo es necesario', 'info']);
switch (name) {
case 'username':
if (value.length < 4 || value.length > 24)
return this.helper.apply(input, ['Debe contener entre 4 y 24 caracteres', 'error']);
if (value === 'white')
return this.helper.apply(input, ['welcome sir! C:', 'success']);
return this.helper.apply(input, ['OK!', 'success']);
break;
case 'email':
var regexp = new RegExp('[0-9a-z=_+\-/][0-9a-z=_\'+\-/\.]*@[\w\-]+(\.[\w\-]+)*(\.[\w]{2,6})$', 'i');
if (!value.match(/^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$/i))
return this.helper.apply(input, ['Email incorrecto', 'error']);
return this.helper.apply(input, ['OK!', 'success']);
break;
case 'password':
if (value.length < 4)
return this.helper.apply(input, ['Ingresa al menos 4 caracteres', 'error']);
if (value === this.cache.inputs.username.value)
return this.helper.apply(input, ['El password debe ser distinto al nickname', 'error']);
return this.helper.apply(input, ['OK!', 'success']);
break;
case 'password2':
if (value !== this.cache.inputs.password.value)
return this.helper.apply(input, ['Las contraseñas no coinciden', 'error']);
return this.helper.apply(input, ['OK!', 'success']);
break;
case 'names':
return this.helper.apply(input, ['OK!', 'success']);
break;
case 'terms':
if (!$(input).is(':checked'))
return this.helper.apply($(input).parent('label'), ['Debes aceptar los terminos', 'error']);
return this.helper.apply($(input).parent('label'), ['OK!', 'success']);
break;
case 'birthday-day':
case 'birthday-month':
case 'birthday-year':
return this.helper.apply($(input).parent('.form-group'), ['OK!', 'success']);
break;
}
},
helper: function(message, status) {
var icon_classes = {
'error': 'glyphicon-remove',
'success': 'glyphicon-ok',
'info': 'glyphicon-info-sign'
}
helperContent = '<span class="glyphicon"></span> <strong>' + message + '</strong>',
container = $(this).is('input') ? $(this).parent() : $(this);
$(this).parent('.form-group').find('.popover').remove();
if ($(this).data('bs.popover')) {
$(this).data('bs.popover').options.content = helperContent;
}
$(this)
.popover({
trigger: 'manual',
animation: true,
html: true,
content: '<span class="glyphicon"></span> <strong>' + message + '</strong>',
placement: 'right',
container: container
})
.popover('show')
.data('bs.popover')
.tip()
.removeClass('error').removeClass('info').removeClass('success')
.addClass(status)
.find('.glyphicon')
.removeClass('glyphicon-remove').removeClass('glyphicon-ok').removeClass('glyphicon-info-sign')
.addClass(icon_classes[status]);
return (status === 'success');
},
public: {}
}, FormValidation.prototype);
return (function(form) {
if (!$) {
throw new Error('Jquery necessary!');
}
return new FormValidation(form).public;
});
}(jQuery));
$(document).ready(function() {
var validation = new FormValidation('.form-validation form');
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment