/* ======================================================================== * Bootstrap (plugin): validator.js v0.9.0 * ======================================================================== * The MIT License (MIT) * * Copyright (c) 2015 Cina Saffary. * Made by @1000hz in the style of Bootstrap 3 era @fat * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * ======================================================================== */ +function ($) { 'use strict'; // VALIDATOR CLASS DEFINITION // ========================== var Validator = function (element, options) { this.$element = $(element) this.options = options options.errors = $.extend({}, Validator.DEFAULTS.errors, options.errors) for (var custom in options.custom) { if (!options.errors[custom]) throw new Error('Missing default error message for custom validator: ' + custom) } $.extend(Validator.VALIDATORS, options.custom) this.$element.attr('novalidate', true) // disable automatic native validation this.toggleSubmit() this.$element.on('input.bs.validator change.bs.validator focusout.bs.validator', $.proxy(this.validateInput, this)) this.$element.on('submit.bs.validator', $.proxy(this.onSubmit, this)) this.$element.find('[data-match]').each(function () { var $this = $(this) var target = $this.data('match') $(target).on('input.bs.validator', function (e) { $this.val() && $this.trigger('input.bs.validator') }) }) } Validator.INPUT_SELECTOR = ':input:not([type="submit"], button):enabled:visible' Validator.DEFAULTS = { delay: 500, html: false, disable: true, custom: {}, errors: { match: 'Does not match', minlength: 'Not long enough' }, feedback: { success: 'glyphicon-ok', error: 'glyphicon-remove' } } Validator.VALIDATORS = { 'native': function ($el) { var el = $el[0] return el.checkValidity ? el.checkValidity() : true }, 'match': function ($el) { var target = $el.data('match') return !$el.val() || $el.val() === $(target).val() }, 'minlength': function ($el) { var minlength = $el.data('minlength') return !$el.val() || $el.val().length >= minlength } } Validator.prototype.validateInput = function (e) { var $el = $(e.target) var prevErrors = $el.data('bs.validator.errors') var errors if ($el.is('[type="radio"]')) $el = this.$element.find('input[name="' + $el.attr('name') + '"]') this.$element.trigger(e = $.Event('validate.bs.validator', {relatedTarget: $el[0]})) if (e.isDefaultPrevented()) return var self = this this.runValidators($el).done(function (errors) { $el.data('bs.validator.errors', errors) errors.length ? self.showErrors($el) : self.clearErrors($el) if (!prevErrors || errors.toString() !== prevErrors.toString()) { e = errors.length ? $.Event('invalid.bs.validator', {relatedTarget: $el[0], detail: errors}) : $.Event('valid.bs.validator', {relatedTarget: $el[0], detail: prevErrors}) self.$element.trigger(e) } self.toggleSubmit() self.$element.trigger($.Event('validated.bs.validator', {relatedTarget: $el[0]})) }) } Validator.prototype.runValidators = function ($el) { var errors = [] var deferred = $.Deferred() var options = this.options $el.data('bs.validator.deferred') && $el.data('bs.validator.deferred').reject() $el.data('bs.validator.deferred', deferred) function getErrorMessage(key) { return $el.data(key + '-error') || $el.data('error') || key == 'native' && $el[0].validationMessage || options.errors[key] } $.each(Validator.VALIDATORS, $.proxy(function (key, validator) { if (($el.data(key) || key == 'native') && !validator.call(this, $el)) { var error = getErrorMessage(key) !~errors.indexOf(error) && errors.push(error) } }, this)) if (!errors.length && $el.val() && $el.data('remote')) { this.defer($el, function () { var data = {} data[$el.attr('name')] = $el.val() $.get($el.data('remote'), data) .fail(function (jqXHR, textStatus, error) { errors.push(getErrorMessage('remote') || error) }) .always(function () { deferred.resolve(errors)}) }) } else deferred.resolve(errors) return deferred.promise() } Validator.prototype.validate = function () { var delay = this.options.delay this.options.delay = 0 this.$element.find(Validator.INPUT_SELECTOR).trigger('input.bs.validator') this.options.delay = delay return this } Validator.prototype.showErrors = function ($el) { var method = this.options.html ? 'html' : 'text' this.defer($el, function () { var $group = $el.closest('.form-group') var $block = $group.find('.help-block.with-errors') var $feedback = $group.find('.form-control-feedback') var errors = $el.data('bs.validator.errors') if (!errors.length) return errors = $('