vendor: 12,363 bytes, lines 1-399
1/*! 2 * Validator v0.11.9 for Bootstrap 3, by @1000hz 3 * Copyright 2017 Cina Saffary 4 * Licensed under http://opensource.org/licenses/MIT 5 * 6 * https://github.com/1000hz/bootstrap-validator 7 */ 8 9+function ($) { 10 'use strict'; 11 12 // VALIDATOR CLASS DEFINITION 13 // ========================== 14 15 function getValue($el) { 16 return $el.is('[type="checkbox"]') ? $el.prop('checked') : 17 $el.is('[type="radio"]') ? !!$('[name="' + $el.attr('name') + '"]:checked').length : 18 $el.is('select[multiple]') ? ($el.val() || []).length : 19 $el.val() 20 } 21 22 var Validator = function (element, options) { 23 this.options = options 24 this.validators = $.extend({}, Validator.VALIDATORS, options.custom) 25 this.$element = $(element) 26 this.$btn = $('button[type="submit"], input[type="submit"]') 27 .filter('[form="' + this.$element.attr('id') + '"]') 28 .add(this.$element.find('input[type="submit"], button[type="submit"]')) 29 30 this.update() 31 32 this.$element.on('input.bs.validator change.bs.validator focusout.bs.validator', $.proxy(this.onInput, this)) 33 this.$element.on('submit.bs.validator', $.proxy(this.onSubmit, this)) 34 this.$element.on('reset.bs.validator', $.proxy(this.reset, this)) 35 36 this.$element.find('[data-match]').each(function () { 37 var $this = $(this) 38 var target = $this.attr('data-match') 39 40 $(target).on('input.bs.validator', function (e) { 41 getValue($this) && $this.trigger('input.bs.validator') 42 }) 43 }) 44 45 // run validators for fields with values, but don't clobber server-side errors 46 this.$inputs.filter(function () { 47 return getValue($(this)) && !$(this).closest('.has-error').length 48 }).trigger('focusout') 49 50 this.$element.attr('novalidate', true) // disable automatic native validation 51 } 52 53 Validator.VERSION = '0.11.9' 54 55 Validator.INPUT_SELECTOR = ':input:not([type="hidden"], [type="submit"], [type="reset"], button)' 56 57 Validator.FOCUS_OFFSET = 20 58 59 Validator.DEFAULTS = { 60 delay: 500, 61 html: false, 62 disable: true, 63 focus: true, 64 custom: {}, 65 errors: { 66 match: 'Does not match', 67 minlength: 'Not long enough', 68 maxlength: 'Not short enough' 69 }, 70 feedback: { 71 success: 'glyphicon-ok', 72 error: 'glyphicon-remove' 73 } 74 } 75 76 Validator.VALIDATORS = { 77 'native': function ($el) { 78 var el = $el[0] 79 if (el.checkValidity) { 80 return !el.checkValidity() && !el.validity.valid && (el.validationMessage || "error!") 81 } 82 }, 83 'match': function ($el) { 84 var target = $el.attr('data-match') 85 return $el.val() !== $(target).val() && Validator.DEFAULTS.errors.match 86 }, 87 'minlength': function ($el) { 88 var minlength = $el.attr('data-minlength') 89 return $el.val().length < minlength && Validator.DEFAULTS.errors.minlength 90 }, 91 'maxlength': function ($el) { 92 var maxlength = $el.attr('data-maxlength') 93 return $el.val().length > maxlength && Validator.DEFAULTS.errors.maxlength 94 } 95 } 96 97 Validator.prototype.update = function () { 98 var self = this 99 100 this.$inputs = this.$element.find(Validator.INPUT_SELECTOR) 101 .add(this.$element.find('[data-validate="true"]')) 102 .not(this.$element.find('[data-validate="false"]') 103 .each(function () { self.clearErrors($(this)) }) 104 ) 105 106 this.toggleSubmit() 107 108 return this 109 } 110 111 Validator.prototype.onInput = function (e) { 112 var self = this 113 var $el = $(e.target) 114 var deferErrors = e.type !== 'focusout' 115 116 if (!this.$inputs.is($el)) return 117 118 this.validateInput($el, deferErrors).done(function () { 119 self.toggleSubmit() 120 }) 121 } 122 123 Validator.prototype.validateInput = function ($el, deferErrors) { 124 var value = getValue($el) 125 var prevErrors = $el.data('bs.validator.errors') 126 127 if ($el.is('[type="radio"]')) $el = this.$element.find('input[name="' + $el.attr('name') + '"]') 128 129 var e = $.Event('validate.bs.validator', {relatedTarget: $el[0]}) 130 this.$element.trigger(e) 131 if (e.isDefaultPrevented()) return 132 133 var self = this 134 135 return this.runValidators($el).done(function (errors) { 136 $el.data('bs.validator.errors', errors) 137 138 errors.length 139 ? deferErrors ? self.defer($el, self.showErrors) : self.showErrors($el) 140 : self.clearErrors($el) 141 142 if (!prevErrors || errors.toString() !== prevErrors.toString()) { 143 e = errors.length 144 ? $.Event('invalid.bs.validator', {relatedTarget: $el[0], detail: errors}) 145 : $.Event('valid.bs.validator', {relatedTarget: $el[0], detail: prevErrors}) 146 147 self.$element.trigger(e) 148 } 149 150 self.toggleSubmit() 151 152 self.$element.trigger($.Event('validated.bs.validator', {relatedTarget: $el[0]})) 153 }) 154 } 155 156 157 Validator.prototype.runValidators = function ($el) { 158 var errors = [] 159 var deferred = $.Deferred() 160 161 $el.data('bs.validator.deferred') && $el.data('bs.validator.deferred').reject() 162 $el.data('bs.validator.deferred', deferred) 163 164 function getValidatorSpecificError(key) { 165 return $el.attr('data-' + key + '-error') 166 } 167 168 function getValidityStateError() { 169 var validity = $el[0].validity 170 return validity.typeMismatch ? $el.attr('data-type-error') 171 : validity.patternMismatch ? $el.attr('data-pattern-error') 172 : validity.stepMismatch ? $el.attr('data-step-error') 173 : validity.rangeOverflow ? $el.attr('data-max-error') 174 : validity.rangeUnderflow ? $el.attr('data-min-error') 175 : validity.valueMissing ? $el.attr('data-required-error') 176 : null 177 } 178 179 function getGenericError() { 180 return $el.attr('data-error') 181 } 182 183 function getErrorMessage(key) { 184 return getValidatorSpecificError(key) 185 || getValidityStateError() 186 || getGenericError() 187 } 188 189 $.each(this.validators, $.proxy(function (key, validator) { 190 var error = null 191 if ((getValue($el) || $el.attr('required')) && 192 ($el.attr('data-' + key) !== undefined || key == 'native') && 193 (error = validator.call(this, $el))) { 194 error = getErrorMessage(key) || error 195 !~errors.indexOf(error) && errors.push(error) 196 } 197 }, this)) 198 199 if (!errors.length && getValue($el) && $el.attr('data-remote')) { 200 this.defer($el, function () { 201 var data = {} 202 data[$el.attr('name')] = getValue($el) 203 $.get($el.attr('data-remote'), data) 204 .fail(function (jqXHR, textStatus, error) { errors.push(getErrorMessage('remote') || error) }) 205 .always(function () { deferred.resolve(errors)}) 206 }) 207 } else deferred.resolve(errors) 208 209 return deferred.promise() 210 } 211 212 Validator.prototype.validate = function () { 213 var self = this 214 215 $.when(this.$inputs.map(function (el) { 216 return self.validateInput($(this), false) 217 })).then(function () { 218 self.toggleSubmit() 219 self.focusError() 220 }) 221 222 return this 223 } 224 225 Validator.prototype.focusError = function () { 226 if (!this.options.focus) return 227 228 var $input = this.$element.find(".has-error :input:first") 229 if ($input.length === 0) return 230 231 $('html, body').animate({scrollTop: $input.offset().top - Validator.FOCUS_OFFSET}, 250) 232 $input.focus() 233 } 234 235 Validator.prototype.showErrors = function ($el) { 236 var method = this.options.html ? 'html' : 'text' 237 var errors = $el.data('bs.validator.errors') 238 var $group = $el.closest('.form-group') 239 var $block = $group.find('.help-block.with-errors') 240 var $feedback = $group.find('.form-control-feedback') 241 242 if (!errors.length) return 243 244 errors = $('<ul/>') 245 .addClass('list-unstyled') 246 .append($.map(errors, function (error) { return $('<li/>')[method](error) })) 247 248 $block.data('bs.validator.originalContent') === undefined && $block.data('bs.validator.originalContent', $block.html()) 249 $block.empty().append(errors) 250 $group.addClass('has-error has-danger') 251 252 $group.hasClass('has-feedback') 253 && $feedback.removeClass(this.options.feedback.success) 254 && $feedback.addClass(this.options.feedback.error) 255 && $group.removeClass('has-success') 256 } 257 258 Validator.prototype.clearErrors = function ($el) { 259 var $group = $el.closest('.form-group') 260 var $block = $group.find('.help-block.with-errors') 261 var $feedback = $group.find('.form-control-feedback') 262 263 $block.html($block.data('bs.validator.originalContent')) 264 $group.removeClass('has-error has-danger has-success') 265 266 $group.hasClass('has-feedback') 267 && $feedback.removeClass(this.options.feedback.error) 268 && $feedback.removeClass(this.options.feedback.success) 269 && getValue($el) 270 && $feedback.addClass(this.options.feedback.success) 271 && $group.addClass('has-success') 272 } 273 274 Validator.prototype.hasErrors = function () { 275 function fieldErrors() { 276 return !!($(this).data('bs.validator.errors') || []).length 277 } 278 279 return !!this.$inputs.filter(fieldErrors).length 280 } 281 282 Validator.prototype.isIncomplete = function () { 283 function fieldIncomplete() { 284 var value = getValue($(this)) 285 return !(typeof value == "string" ? $.trim(value) : value) 286 } 287 288 return !!this.$inputs.filter('[required]').filter(fieldIncomplete).length 289 } 290 291 Validator.prototype.onSubmit = function (e) { 292 this.validate() 293 if (this.isIncomplete() || this.hasErrors()) e.preventDefault() 294 } 295 296 Validator.prototype.toggleSubmit = function () { 297 if (!this.options.disable) return 298 this.$btn.toggleClass('disabled', this.isIncomplete() || this.hasErrors()) 299 } 300 301 Validator.prototype.defer = function ($el, callback) { 302 callback = $.proxy(callback, this, $el) 303 if (!this.options.delay) return callback() 304 window.clearTimeout($el.data('bs.validator.timeout')) 305 $el.data('bs.validator.timeout', window.setTimeout(callback, this.options.delay)) 306 } 307 308 Validator.prototype.reset = function () { 309 this.$element.find('.form-control-feedback') 310 .removeClass(this.options.feedback.error) 311 .removeClass(this.options.feedback.success) 312 313 this.$inputs 314 .removeData(['bs.validator.errors', 'bs.validator.deferred']) 315 .each(function () { 316 var $this = $(this) 317 var timeout = $this.data('bs.validator.timeout') 318 window.clearTimeout(timeout) && $this.removeData('bs.validator.timeout') 319 }) 320 321 this.$element.find('.help-block.with-errors') 322 .each(function () { 323 var $this = $(this) 324 var originalContent = $this.data('bs.validator.originalContent') 325 326 $this 327 .removeData('bs.validator.originalContent') 328 .html(originalContent) 329 }) 330 331 this.$btn.removeClass('disabled') 332 333 this.$element.find('.has-error, .has-danger, .has-success').removeClass('has-error has-danger has-success') 334 335 return this 336 } 337 338 Validator.prototype.destroy = function () { 339 this.reset() 340 341 this.$element 342 .removeAttr('novalidate') 343 .removeData('bs.validator') 344 .off('.bs.validator') 345 346 this.$inputs 347 .off('.bs.validator') 348 349 this.options = null 350 this.validators = null 351 this.$element = null 352 this.$btn = null 353 this.$inputs = null 354 355 return this 356 } 357 358 // VALIDATOR PLUGIN DEFINITION 359 // =========================== 360 361 362 function Plugin(option) { 363 return this.each(function () { 364 var $this = $(this) 365 var options = $.extend({}, Validator.DEFAULTS, $this.data(), typeof option == 'object' && option) 366 var data = $this.data('bs.validator') 367 368 if (!data && option == 'destroy') return 369 if (!data) $this.data('bs.validator', (data = new Validator(this, options))) 370 if (typeof option == 'string') data[option]() 371 }) 372 } 373 374 var old = $.fn.validator 375 376 $.fn.validator = Plugin 377 $.fn.validator.Constructor = Validator 378 379 380 // VALIDATOR NO CONFLICT 381 // ===================== 382 383 $.fn.validator.noConflict = function () { 384 $.fn.validator = old 385 return this 386 } 387 388 389 // VALIDATOR DATA-API 390 // ================== 391 392 $(window).on('load', function () { 393 $('form[data-toggle="validator"]').each(function () { 394 var $form = $(this) 395 Plugin.call($form, $form.data()) 396 }) 397 }) 398 399}(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.