corrade-nucleus-nucleons – Blame information for rev 20

Subversion Repositories:
Rev:
Rev Author Line No. Line
20 office 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 },
69 feedback: {
70 success: 'glyphicon-ok',
71 error: 'glyphicon-remove'
72 }
73 }
74  
75 Validator.VALIDATORS = {
76 'native': function ($el) {
77 var el = $el[0]
78 if (el.checkValidity) {
79 return !el.checkValidity() && !el.validity.valid && (el.validationMessage || "error!")
80 }
81 },
82 'match': function ($el) {
83 var target = $el.attr('data-match')
84 return $el.val() !== $(target).val() && Validator.DEFAULTS.errors.match
85 },
86 'minlength': function ($el) {
87 var minlength = $el.attr('data-minlength')
88 return $el.val().length < minlength && Validator.DEFAULTS.errors.minlength
89 }
90 }
91  
92 Validator.prototype.update = function () {
93 var self = this
94  
95 this.$inputs = this.$element.find(Validator.INPUT_SELECTOR)
96 .add(this.$element.find('[data-validate="true"]'))
97 .not(this.$element.find('[data-validate="false"]')
98 .each(function () { self.clearErrors($(this)) })
99 )
100  
101 this.toggleSubmit()
102  
103 return this
104 }
105  
106 Validator.prototype.onInput = function (e) {
107 var self = this
108 var $el = $(e.target)
109 var deferErrors = e.type !== 'focusout'
110  
111 if (!this.$inputs.is($el)) return
112  
113 this.validateInput($el, deferErrors).done(function () {
114 self.toggleSubmit()
115 })
116 }
117  
118 Validator.prototype.validateInput = function ($el, deferErrors) {
119 var value = getValue($el)
120 var prevErrors = $el.data('bs.validator.errors')
121  
122 if ($el.is('[type="radio"]')) $el = this.$element.find('input[name="' + $el.attr('name') + '"]')
123  
124 var e = $.Event('validate.bs.validator', {relatedTarget: $el[0]})
125 this.$element.trigger(e)
126 if (e.isDefaultPrevented()) return
127  
128 var self = this
129  
130 return this.runValidators($el).done(function (errors) {
131 $el.data('bs.validator.errors', errors)
132  
133 errors.length
134 ? deferErrors ? self.defer($el, self.showErrors) : self.showErrors($el)
135 : self.clearErrors($el)
136  
137 if (!prevErrors || errors.toString() !== prevErrors.toString()) {
138 e = errors.length
139 ? $.Event('invalid.bs.validator', {relatedTarget: $el[0], detail: errors})
140 : $.Event('valid.bs.validator', {relatedTarget: $el[0], detail: prevErrors})
141  
142 self.$element.trigger(e)
143 }
144  
145 self.toggleSubmit()
146  
147 self.$element.trigger($.Event('validated.bs.validator', {relatedTarget: $el[0]}))
148 })
149 }
150  
151  
152 Validator.prototype.runValidators = function ($el) {
153 var errors = []
154 var deferred = $.Deferred()
155  
156 $el.data('bs.validator.deferred') && $el.data('bs.validator.deferred').reject()
157 $el.data('bs.validator.deferred', deferred)
158  
159 function getValidatorSpecificError(key) {
160 return $el.attr('data-' + key + '-error')
161 }
162  
163 function getValidityStateError() {
164 var validity = $el[0].validity
165 return validity.typeMismatch ? $el.attr('data-type-error')
166 : validity.patternMismatch ? $el.attr('data-pattern-error')
167 : validity.stepMismatch ? $el.attr('data-step-error')
168 : validity.rangeOverflow ? $el.attr('data-max-error')
169 : validity.rangeUnderflow ? $el.attr('data-min-error')
170 : validity.valueMissing ? $el.attr('data-required-error')
171 : null
172 }
173  
174 function getGenericError() {
175 return $el.attr('data-error')
176 }
177  
178 function getErrorMessage(key) {
179 return getValidatorSpecificError(key)
180 || getValidityStateError()
181 || getGenericError()
182 }
183  
184 $.each(this.validators, $.proxy(function (key, validator) {
185 var error = null
186 if ((getValue($el) || $el.attr('required')) &&
187 ($el.attr('data-' + key) !== undefined || key == 'native') &&
188 (error = validator.call(this, $el))) {
189 error = getErrorMessage(key) || error
190 !~errors.indexOf(error) && errors.push(error)
191 }
192 }, this))
193  
194 if (!errors.length && getValue($el) && $el.attr('data-remote')) {
195 this.defer($el, function () {
196 var data = {}
197 data[$el.attr('name')] = getValue($el)
198 $.get($el.attr('data-remote'), data)
199 .fail(function (jqXHR, textStatus, error) { errors.push(getErrorMessage('remote') || error) })
200 .always(function () { deferred.resolve(errors)})
201 })
202 } else deferred.resolve(errors)
203  
204 return deferred.promise()
205 }
206  
207 Validator.prototype.validate = function () {
208 var self = this
209  
210 $.when(this.$inputs.map(function (el) {
211 return self.validateInput($(this), false)
212 })).then(function () {
213 self.toggleSubmit()
214 self.focusError()
215 })
216  
217 return this
218 }
219  
220 Validator.prototype.focusError = function () {
221 if (!this.options.focus) return
222  
223 var $input = this.$element.find(".has-error:first :input")
224 if ($input.length === 0) return
225  
226 $('html, body').animate({scrollTop: $input.offset().top - Validator.FOCUS_OFFSET}, 250)
227 $input.focus()
228 }
229  
230 Validator.prototype.showErrors = function ($el) {
231 var method = this.options.html ? 'html' : 'text'
232 var errors = $el.data('bs.validator.errors')
233 var $group = $el.closest('.form-group')
234 var $block = $group.find('.help-block.with-errors')
235 var $feedback = $group.find('.form-control-feedback')
236  
237 if (!errors.length) return
238  
239 errors = $('<ul/>')
240 .addClass('list-unstyled')
241 .append($.map(errors, function (error) { return $('<li/>')[method](error) }))
242  
243 $block.data('bs.validator.originalContent') === undefined && $block.data('bs.validator.originalContent', $block.html())
244 $block.empty().append(errors)
245 $group.addClass('has-error has-danger')
246  
247 $group.hasClass('has-feedback')
248 && $feedback.removeClass(this.options.feedback.success)
249 && $feedback.addClass(this.options.feedback.error)
250 && $group.removeClass('has-success')
251 }
252  
253 Validator.prototype.clearErrors = function ($el) {
254 var $group = $el.closest('.form-group')
255 var $block = $group.find('.help-block.with-errors')
256 var $feedback = $group.find('.form-control-feedback')
257  
258 $block.html($block.data('bs.validator.originalContent'))
259 $group.removeClass('has-error has-danger has-success')
260  
261 $group.hasClass('has-feedback')
262 && $feedback.removeClass(this.options.feedback.error)
263 && $feedback.removeClass(this.options.feedback.success)
264 && getValue($el)
265 && $feedback.addClass(this.options.feedback.success)
266 && $group.addClass('has-success')
267 }
268  
269 Validator.prototype.hasErrors = function () {
270 function fieldErrors() {
271 return !!($(this).data('bs.validator.errors') || []).length
272 }
273  
274 return !!this.$inputs.filter(fieldErrors).length
275 }
276  
277 Validator.prototype.isIncomplete = function () {
278 function fieldIncomplete() {
279 var value = getValue($(this))
280 return !(typeof value == "string" ? $.trim(value) : value)
281 }
282  
283 return !!this.$inputs.filter('[required]').filter(fieldIncomplete).length
284 }
285  
286 Validator.prototype.onSubmit = function (e) {
287 this.validate()
288 if (this.isIncomplete() || this.hasErrors()) e.preventDefault()
289 }
290  
291 Validator.prototype.toggleSubmit = function () {
292 if (!this.options.disable) return
293 this.$btn.toggleClass('disabled', this.isIncomplete() || this.hasErrors())
294 }
295  
296 Validator.prototype.defer = function ($el, callback) {
297 callback = $.proxy(callback, this, $el)
298 if (!this.options.delay) return callback()
299 window.clearTimeout($el.data('bs.validator.timeout'))
300 $el.data('bs.validator.timeout', window.setTimeout(callback, this.options.delay))
301 }
302  
303 Validator.prototype.reset = function () {
304 this.$element.find('.form-control-feedback')
305 .removeClass(this.options.feedback.error)
306 .removeClass(this.options.feedback.success)
307  
308 this.$inputs
309 .removeData(['bs.validator.errors', 'bs.validator.deferred'])
310 .each(function () {
311 var $this = $(this)
312 var timeout = $this.data('bs.validator.timeout')
313 window.clearTimeout(timeout) && $this.removeData('bs.validator.timeout')
314 })
315  
316 this.$element.find('.help-block.with-errors')
317 .each(function () {
318 var $this = $(this)
319 var originalContent = $this.data('bs.validator.originalContent')
320  
321 $this
322 .removeData('bs.validator.originalContent')
323 .html(originalContent)
324 })
325  
326 this.$btn.removeClass('disabled')
327  
328 this.$element.find('.has-error, .has-danger, .has-success').removeClass('has-error has-danger has-success')
329  
330 return this
331 }
332  
333 Validator.prototype.destroy = function () {
334 this.reset()
335  
336 this.$element
337 .removeAttr('novalidate')
338 .removeData('bs.validator')
339 .off('.bs.validator')
340  
341 this.$inputs
342 .off('.bs.validator')
343  
344 this.options = null
345 this.validators = null
346 this.$element = null
347 this.$btn = null
348 this.$inputs = null
349  
350 return this
351 }
352  
353 // VALIDATOR PLUGIN DEFINITION
354 // ===========================
355  
356  
357 function Plugin(option) {
358 return this.each(function () {
359 var $this = $(this)
360 var options = $.extend({}, Validator.DEFAULTS, $this.data(), typeof option == 'object' && option)
361 var data = $this.data('bs.validator')
362  
363 if (!data && option == 'destroy') return
364 if (!data) $this.data('bs.validator', (data = new Validator(this, options)))
365 if (typeof option == 'string') data[option]()
366 })
367 }
368  
369 var old = $.fn.validator
370  
371 $.fn.validator = Plugin
372 $.fn.validator.Constructor = Validator
373  
374  
375 // VALIDATOR NO CONFLICT
376 // =====================
377  
378 $.fn.validator.noConflict = function () {
379 $.fn.validator = old
380 return this
381 }
382  
383  
384 // VALIDATOR DATA-API
385 // ==================
386  
387 $(window).on('load', function () {
388 $('form[data-toggle="validator"]').each(function () {
389 var $form = $(this)
390 Plugin.call($form, $form.data())
391 })
392 })
393  
394 }(jQuery);