PageSourceSearch

https://www.minmaxpower.com/frontend/npm_package/bootstrap-validator-master/dist/validator.js?v=20220801

js minmaxpower.com collected 2026-10-04 02:13:29 UTC 25,348 bytes, 701 lines download raw bytes

1/*!
2 * Validator v0.11.9 for Bootstrap 3, by @1000hz
3 * Copyright 2021 Cina Saffary
4 * Licensed under http://opensource.org/licenses/MIT
5 *
6 * https://github.com/1000hz/bootstrap-validator
7 */
8
9window.validateRequest = {};
10
11+function ($) {
12  'use strict';
13
14  // VALIDATOR CLASS DEFINITION
15  // ==========================
16
17  function getValue($el) {
18    return $el.is('[type="checkbox"]') ? $el.parents('.form-group').find('[name="' + $el.attr('name') + '"]:checked').length :
19           $el.is('[type="radio"]')    ? !!$('[name="' + $el.attr('name') + '"]:checked').length                             :
20           $el.is('select[multiple]')  ? ($el.val() || []).length                                                            :
21           $el.val()
22  }
23
24  var Validator = function (element, options) {
25    this.options    = options
26    this.validators = $.extend({}, Validator.VALIDATORS, options.custom)
27    this.$element   = $(element)
28    this.$btn       = $('button[type="submit"], input[type="submit"]')
29                        .filter('[form="' + this.$element.attr('id') + '"]')
30                        .add(this.$element.find('input[type="submit"], button[type="submit"]'))
31
32    this.update()
33
34    this.$element.on('input.bs.validator change.bs.validator focusout.bs.validator', $.proxy(this.onInput, this))
35    this.$element.on('submit.bs.validator', $.proxy(this.onSubmit, this))
36    this.$element.on('reset.bs.validator', $.proxy(this.reset, this))
37
38    this.$element.find('[data-match]').each(function () {
39      var $this  = $(this)
40      var target = $this.attr('data-match')
41      var $target = $(target)
42      $this.on('input.bs.validator', function (e) {
43          $this.prop('validating', true);
44      })
45      $target.on('input.bs.validator', function (e) {
46          if ($this.prop('validating')) {
47              $this.prop('validating', false)
48              getValue($this) && $this.trigger('input.bs.validator')
49          }
50      })
51    })
52
53    // run validators for fields with values, but don't clobber server-side errors
54    this.$inputs.filter(function () {
55      return getValue($(this)) && !$(this).closest('.has-error').length
56    }).trigger('focusout')
57
58    this.$element.attr('novalidate', true) // disable automatic native validation
59  }
60
61  Validator.VERSION = '0.11.9'
62
63  Validator.INPUT_SELECTOR = ':input:not([type="hidden"], [type="submit"], [type="reset"], button)'
64
65  Validator.FOCUS_OFFSET = 20
66
67  Validator.DEFAULTS = {
68    delay: 500,
69    html: false,
70    disable: true,
71    focus: true,
72    custom: {},
73    errors: {
74      match: 'Does not match',
75      minlength: 'Not long enough',
76      maxlength: 'Too long'
77    },
78    feedback: {
79      success: 'glyphicon-ok',
80      error: 'glyphicon-remove'
81    }
82  }
83
84  Validator.VALIDATORS = {
85    'native': function ($el) {
86      var el = $el[0]
87
88      if ($el.is('[data-related=true]')) {
89        return this.ValidateRelate($el)
90      } else if ($el.is('[type=checkbox][required]')) {
91        if (getValue($el) <= 0) {
92          return !el.checkValidity() && !el.validity.valid && (el.validationMessage || "error!")
93        }
94      } else if ($el.is('[type=url]')) {
95        return this.ValidateURL($el)
96      } else if ($el.is('[type=captcha]')) {
97        return this.ValidateCaptcha($el)
98      }
99      // else if ($el.is('[type=email]')) {
100      //   return this.ValidateEmail($el)
101      // }
102      else {
103        if (el.checkValidity) {
104          return !el.checkValidity() && !el.validity.valid && (el.validationMessage || "error!")
105        }
106      }
107    },
108    'match': function ($el) {
109      var target = $el.attr('data-match')
110
111      return $el.val() !== $(target).val() && Validator.DEFAULTS.errors.match
112    },
113    'minlength': function ($el) {
114      var minlength = $el.attr('data-minlength')
115
116      return $el.is('[type=checkbox]') ? getValue($el) < minlength && Validator.DEFAULTS.errors.minlength : $el.val().length < minlength && Validator.DEFAULTS.errors.minlength
117    },
118    'maxlength': function ($el) {
119      var maxlength = $el.attr('data-maxlength')
120
121      return $el.is('[type=checkbox]') ? getValue($el) > maxlength && Validator.DEFAULTS.errors.maxlength : $el.val().length > maxlength && Validator.DEFAULTS.errors.maxlength
122    }
123  }
124
125  Validator.prototype.ValidateURL = function ($el) {
126    var el = $el[0]
127    var formGroup = $el.parents('.form-group')
128
129    if (el.checkValidity) {
130      if (!el.checkValidity()){
131        return !el.validity.valid && (el.validationMessage || "error!")
132      } else {
133        if ($el.attr('data-temp-value') != $el.val()) {
134          formGroup.removeClass('has-success has-error').addClass("is-loading")
135          $.ajax({
136            url: $el.val(),
137            type: 'GET',
138            dataType: "jsonp",
139            crossDomain: true,
140            async: false,
141            complete: function(response) {
142              formGroup.removeClass('has-success has-error').addClass([response.status == 200 ? "has-success" : "has-error"]).removeClass("is-loading")
143              $el.attr('data-temp-value', $el.val())
144              formGroup.find('.help-block.with-errors').find('*:not(:has(*))').last().text((window.validator.UrlFail || 'connected fail').replace(/%s/g, formGroup.last().find('.b-form__label').text()))
145              formGroup.parents('form').data('bs.validator').toggleSubmit()
146            },
147          })
148        } else {
149          if (formGroup.is('.has-error') && formGroup.is(':not(.is-loading)')) {
150            return (window.validator.UrlFail || 'connected fail').replace(/%s/g, formGroup.last().find('.b-form__label').text())
151          }
152        }
153
154      }
155    }
156  }
157  // Validator.prototype.ValidateEmail = function ($el) {
158  //   var el = $el[0]
159  //   var formGroup = $el.parents('.form-group')
160  //
161  //   if (el.checkValidity) {
162  //     if (!el.checkValidity()){
163  //       return !el.validity.valid && (el.validationMessage || "error!")
164  //     } else {
165  //       if ($el.attr('data-temp-value') != $el.val()) {
166  //         var type = 'email'
167  //         formGroup.removeClass('has-success has-error').addClass("is-loading")
168  //         $.ajax({
169  //           url : '/library/check-email',
170  //           type : 'post',
171  //           data : {"email": $el.val(), "_token": $('meta[name=csrf-token]').attr('content') },
172  //           beforeSend: function( xhr ) {
173  //             $this.css('cursor', 'not-allowed');
174  //             if (window.validateRequest[type] != null){
175  //               window.validateRequest[type].abort();
176  //             }
177  //             window.validateRequest[type] = xhr;
178  //           },
179  //           complete: function(response) {
180  //             if (response.status == 200) {
181  //               formGroup.removeClass('has-success has-error').addClass([response.responseJSON.is_reachable != 'invali
181d' ? "has-success" : "has-error"]).removeClass("is-loading")
182  //               $el.attr('data-temp-value', $el.val())
183  //               formGroup.find('.help-block.with-errors').find('*:not(:has(*))').last().text((window.validator.EmailFail || 'connected fail').replace(/%s/g, formGroup.last().find('.b-form__label').text()))
184  //               formGroup.parents('form').data('bs.validator').toggleSubmit()
185  //             }
186  //             window.validateRequest[type] = null
187  //
188  //           },
189  //         })
190  //       } else {
191  //         if (formGroup.is('.has-error') && formGroup.is(':not(.is-loading)')) {
192  //           return (window.validator.EmailFail || 'connected fail').replace(/%s/g, formGroup.last().find('.b-form__label').text())
193  //         }
194  //       }
195  //
196  //     }
197  //   }
198  // }
199  Validator.prototype.ValidateCaptcha = function ($el) {
200    var el = $el[0]
201    var formGroup = $el.parents('.form-group')
202
203    if (el.checkValidity) {
204      if (!el.checkValidity()){
205        return !el.validity.valid && (el.validationMessage || "error!")
206      } else {
207        if ($el.attr('data-temp-value') != $el.val()) {
208          formGroup.removeClass('has-success has-error').addClass("is-loading")
209          $.post(
210            "/captcha",
211            {
212              captcha: $el.val(),
213              _token: $('meta[name=csrf-token]').attr('content')
214            }
215          ).always(function (response) {
216              formGroup.removeClass('has-success has-error').addClass([JSON.parse(response)['response'] ? "has-success" : "has-error"]).removeClass("is-loading")
217              $el.attr('data-temp-value', $el.val())
218              formGroup.find('.help-block.with-errors').find('*:not(:has(*))').last().text((window.validator.CaptchaFail || 'wrong Captcha').replace(/%s/g, formGroup.last().find('.b-form__label').text()))
219              formGroup.parents('form').data('bs.validator').toggleSubmit()
220          })
221        } else {
222          if (formGroup.is('.has-error') && formGroup.is(':not(.is-loading)')) {
223            return (window.validator.CaptchaFail || 'wrong Captcha').replace(/%s/g, formGroup.last().find('.b-form__label').text())
224          }
225        }
226
227      }
228    }
229  }
230
231  Validator.prototype.AddreCAPTCHAToken = function ($el, event) {
232    var form = this.$element;
233    var now = new Date()
234    var oldTokenTime = Date.parse(localStorage.getItem('google-recaptcha-updated-at'))
235    if (
236      $el.val() == ''
237      || isNaN(oldTokenTime)
238      // 1.5分鐘
239      || (now - oldTokenTime) > 90000
240      ) {
241      event.preventDefault()
242      grecaptcha.ready(function() {
243        grecaptcha.execute($el.data('site-key'), {action: 'submit'}).then(function(token, event) {
244          $el.val(token);
245          localStorage.setItem('google-recaptcha-updated-at', new Date())
246          form.submit();
247        });
248      });
249    }
250
251    return;
252  }
253
254  Validator.prototype.ValidateRelate = function ($el) {
255    var formGroup = $el.parents('.form-group')
256    var formGroupsGroup = $el.parents('.form-group.has-child')
257    var AllInputs = formGroupsGroup.find('input, textarea, select')
258    var needCheckAll = false
259    var formGroupsGroupPass = true
260
261    AllInputs.each(function (){
262      if (getValue($(this))){
263        needCheckAll = true
264        return;
265      }
266      if (this.checkValidity) {
267        !!(!this.checkValidity() && !this.validity.valid && (this.validationMessage || "error!")) && (needCheckAll = true)
268        return;
269      }
270    })
271
272    if (needCheckAll) {
273      AllInputs.each(function () {
274        if (! getValue($(this))) {
275          formGroupsGroupPass = false
276          $(this).parents('.form-group').removeClass('has-success').addClass('has-error')
277        }
278        if (this.checkValidity) {
279          !!(!this.checkValidity() && !this.validity.valid && (this.validationMessage || "error!")) && (formGroupsGroupPass = false) && $(this).parents('.form-group').removeClass('has-success').addClass('has-error')
280          return;
281        }
282      })
283    }
284    formGroupsGroup.removeClass('has-group-error has-group-success has-error has-success')
285    needCheckAll && formGroupsGroup.addClass(formGroupsGroupPass ? 'has-group-success' : 'has-group-error')
286    !needCheckAll && formGroupsGroup.find('.form-group').removeClass('has-error has-success')
287
288    if ( needCheckAll ) {
289      var validityMessage;
290      var el = $el[0]
291
292      if (el.checkValidity) {
293        validityMessage = !el.checkValidity() && !el.validity.valid && (el.validationMessage || "error!")
294      }
295      if (!validityMessage) {
296        var isRequired = $el.is('[required]')
297        !isRequired && $el.attr('required', true)
298
299        if (el.checkValidity) {
300          validityMessage = !el.checkValidity() && !el.validity.valid && (el.validationMessage || "error!")
301        }
302        !isRequired && $el.removeAttr('required')
303
304      }
305      return validityMessage
306    }
307  }
308
309  Validator.prototype.update = function () {
310    var self = this
311
312    this.$inputs = this.$element.find(Validator.INPUT_SELECTOR)
313      .add(this.$element.find('[data-validate="true"]'))
314      .not(this.$element.find('[data-validate="false"]')
315        .each(function () { self.clearErrors($(this)) })
316      )
317
318    this.toggleSubmit()
319
320    return this
321  }
322
323  Validator.prototype.onInput = function (e) {
324    var self        = this
325    var $el         = $(e.target)
326    var deferErrors = e.type !== 'focusout'
327
328    if (!this.$inputs.is($el)) return
329
330    this.validateInput($el, deferErrors).done(function () {
331      self.toggleSubmit()
332    })
333  }
334
335  Validator.prototype.validateInput = function ($el, deferErrors, event) {
336    var value      = getValue($el)
337    var prevErrors = $el.data('bs.validator.errors')
338
339    if ($el.is('[type="radio"]')) $el = this.$element.find('input[name="' + $el.attr('name') + '"]')
340
341    if ($el.is('[type="google-recaptcha"]')) this.AddreCAPTCHAToken($el, event)
342
343    var e = $.Event('validate.bs.validator', {relatedTarget: $el[0]})
344    this.$element.trigger(e)
345    if (e.isDefaultPrevented()) return
346
347    var self = this
348
349    return this.runValidators($el).done(function (errors) {
350      $el.data('bs.validator.errors', errors)
351
352      errors.length
353        ? deferErrors ? self.defer($el, self.showErrors) : self.showErrors($el)
354        : self.clearErrors($el)
355
356      if (!prevErrors || errors.toString() !== prevErrors.toString()) {
357        e = errors.length
358          ? $.Event('invalid.bs.validator', {relatedTarget: $el[0], detail: errors})
359          : $.Event('valid.bs.validator', {relatedTarget: $el[0], detail: prevErrors})
360
361        self.$element.trigger(e)
362      }
363
364      self.toggleSubmit()
365
366      self.$element.trigger($.Event('validated.bs.validator', {relatedTarget: $el[0]}))
367    })
368  }
369
370
371  Validator.prototype.runValidators = function ($el) {
372    var errors   = []
373    var deferred = $.Deferred()
374
375    $el.data('bs.validator.deferred') && $el.data('bs.validator.deferred').reject()
376    $el.data('bs.validator.deferred', deferred)
377
378    function getValidatorSpecificError(key) {
379      return $el.attr('data-' + key + '-error')
380    }
381
382    function getValidityStateError() {
383      var validity = $el[0].validity
384      return validity.typeMismatch    ? $el.attr('data-type-error')
385           : validity.patternMismatch ? $el.attr('data-pattern-error')
386           : validity.stepMismatch    ? $el.attr('data-step-error')
387           : validity.rangeOverflow   ? $el.attr('data-max-error')
388           : validity.rangeUnderflow  ? $el.attr('data-min-error')
389           : validity.valueMissing    ? $el.attr('data-required-error')
390           :                            null
391    }
392
393    function getGenericError() {
394      return $el.attr('data-error')
395    }
396
397    function getErrorMessage(key) {
398      return getValidatorSpecificError(key)
399          || getValidityStateError()
400          || getGenericError()
401    }
402    $.each(this.validators, $.proxy(function (key, validator) {
403      var error = null
404
405      if ((getValue($el) || $el.attr('required') || $el.is('[data-related=true]')) &&
406          ($el.attr('data-' + key) !== undefined || key == 'native') &&
407          (error = validator.call(this, $el))) {
408         error = getErrorMessage(key) || error
409        !~errors.indexOf(error) && errors.push(error)
410      }
411    }, this))
412    if (!errors.length && getValue($el) && $el.attr('data-remote')) {
413      this.defer($el, function () {
414        var data = {}
415        data[$el.attr('name')] = getValue($el)
416        $.get($el.attr('data-remote'), data)
417          .fail(function (jqXHR, textStatus, error) { errors.push(getErrorMessage('remote') || error) })
418          .always(function () { deferred.resolve(errors)})
419      })
420    } else deferred.resolve(errors)
421
422    return deferred.promise()
423  }
424
425  Validator.prototype.validate = function (e) {
426    var self = this
427
428    var event = e
429    $.when(this.$inputs.map(function (el) {
430      return self.validateInput($(this), false, event)
431    })).then(function () {
432      self.toggleSubmit()
433      self.focusError()
434    })
435
436    return this
437  }
438
439  Validator.prototype.focusError = function () {
440    if (!this.options.focus) return
441
442    var $input = this.$element.find('.has-error,.is-loading').first().find('input, select, textarea')
443    if ($input.length === 0) return
444
445    $('html, body').animate({scrollTop: $input.offset().top - Validator.FOCUS_OFFSET}, 250)
446    $input.is(':not(select)') && $input.focus()
447  }
448
449  Validator.prototype.showErrors = function ($el) {
450    var method = this.options.html ? 'html' : 'text'
451    var errors = $el.data('bs.validator.errors')
452    var $group = $el.closest('.form-group')
453    var $block = $group.find('.help-block.with-errors')
454    var $feedback = $group.find('.form-control-feedback')
455
456    if (!errors.length) return
457
458    errors = $('<ul/>')
459      .addClass('list-unstyled')
460      .append($.map(errors, function (error) { return $('<li/>')[method](error) }))
461
462    $block.data('bs.validator.originalContent') === undefined && $block.data('bs.validator.originalContent', $block.html())
463    $block.empty().append(errors)
464    $group.addClass('has-error has-danger')
465
466    $group.hasClass('has-feedback')
467      && $feedback.removeClass(this.options.feedback.success)
468      && $feedback.addClass(this.options.feedback.error)
469      && $group.removeClass('has-success')
470  }
471
472  Validator.prototype.clearErrors = function ($el) {
473    var $group = $el.closest('.form-group')
474    var $block = $group.find('.help-block.with-errors')
475    var $feedback = $group.find('.form-control-feedback')
476
477    $block.html($block.data('bs.validator.originalContent'))
478    $group.removeClass('has-error has-danger has-success')
479
480    $group.hasClass('has-feedback')
481      && $feedback.removeClass(this.options.feedback.error)
482      && $feedback.removeClass(this.options.feedback.success)
483      && getValue($el)
484      && $feedback.addClass(this.options.feedback.success)
485      && $group.addClass('has-success')
486  }
487
488  Validator.prototype.hasErrors = function () {
489    function fieldErrors() {
490      return !!($(this).data('bs.validator.errors') || []).length
491    }
492
493    return !!this.$inputs.filter(fieldErrors).length
494  }
495
496  Validator.prototype.isIncomplete = function () {
497    function fieldIncomplete() {
498      var value = getValue($(this))
499      return !(typeof value == "string" ? $.trim(value) : value)
500    }
501
502    return !!this.$inputs.filter('[required]').filter(fieldIncomplete).length
503  }
504  Validator.prototype.isLoading = function () {
505    return !!this.$inputs.filter('.is-loading *').length
506  }
507
508  Validator.prototype.onSubmit = function (e) {
509    this.validate(e)
510    if (this.isIncomplete() || this.hasErrors() || this.isLoading()) e.preventDefault()
511  }
512
513  Validator.prototype.toggleSubmit = function () {
514    if (!this.options.disable) return
515    this.$btn.toggleClass('disabled', this.isIncomplete() || this.hasErrors() || this.isLoading())
516  }
517
518  Validator.prototype.defer = function ($el, callback) {
519    callback = $.proxy(callback, this, $el)
520    if (!this.options.delay) return callback()
521    window.clearTimeout($el.data('bs.validator.timeout'))
522    $el.data('bs.validator.timeout', window.setTimeout(callback, this.options.delay))
523  }
524
525  Validator.prototype.reset = function () {
526    this.$element.find('.form-control-feedback')
527      .removeClass(this.options.feedback.error)
528      .removeClass(this.options.feedback.success)
529
530    this.$inputs
531      .removeData(['bs.validator.errors', 'bs.validator.deferred'])
532      .each(function () {
533        var $this = $(this)
534        var timeout = $this.data('bs.validator.timeout')
535        window.clearTimeout(timeout) && $this.removeData('bs.validator.timeout')
536      })
537
538    this.$element.find('.help-block.with-errors')
539      .each(function () {
540        var $this = $(this)
541        var originalContent = $this.data('bs.validator.originalContent')
542
543        $this
544          .removeData('bs.validator.originalContent')
545          .html(originalContent)
546      })
547
548    this.$btn.removeClass('disabled')
549
550    this.$element.find('.has-error, .has-danger, .has-success').removeClass('has-error has-danger has-success')
551
552    return this
553  }
554
555  Validator.prototype.destroy = function () {
556    this.reset()
557
558    this.$element
559      .removeAttr('novalidate')
560      .removeData('bs.validator')
561      .off('.bs.validator')
562
563    this.$inputs
564      .off('.bs.validator')
565
566    this.options    = null
567    this.validators = null
568    this.$element   = null
569    this.$btn       = null
570    this.$inputs    = null
571
572    return this
573  }
574
575  // VALIDATOR PLUGIN DEFINITION
576  // ===========================
577
578
579  function Plugin(option) {
580    return this.each(function () {
581      var $this   = $(this)
582      var options = $.extend({}, Validator.DEFAULTS, $this.data(), typeof option == 'object' && option)
583      var data    = $this.data('bs.validator')
584
585      if (!data && option == 'destroy') return
586      if (!data) $this.data('bs.validator', (data = new Validator(this, options)))
587      if (typeof option == 'string') data[option]()
588
589      var $childFormGroup = $this.find('.form-group');
590      $childFormGroup.addClass('has-feedback').filter(':has(".form-group")').addClass('has-child').filter(':has(".form-group label")').addClass('has-child-label')
591      $childFormGroup.filter(':not(:has(".form-group"))').addClass('is-child')
592      var $childIsChildInput = $this.find('.is-child:has(input, select, textarea)');
593      $childIsChildInput.filter(':has(input[type=text]), :has(input[type=email]), :has(input[type=url]), :has(input[type=number]), :has(input[type=tel])').addClass('is-textinput')
594      $childIsChildInput.filter(':has(input[type=radio])').addClass('is-radio')
595      $childIsChildInput.filter(':has(select)').addClass('is-select')
596      $childIsChildInput.filter(':has(textarea)').addClass('is-textarea').not(':has(".textarea_feedback")').find('textarea').each(function() {
597        var maxLength = $(this).attr('maxlength');
598        if (maxLength) {
599          var resizing = null;
600
601          $(this).next().not('.textarea_feedback') && $(this).after("<div class='textarea_feedback'>"+ maxLength + '/' + maxLength + "</div>")
602
603          $(this).on('propertychange input', function() {
604            $(this).next('.textarea_feedback').html(maxLength - $(this).val().length + '/' + maxLength);
605          }).mousedown(function() {
606            var nowThis = $(this);
607            resizing = setInterval(
608                function() {
609                nowThis.next().width('calc(' + nowThis.width() +'px + ' + nowThis.css('padding-right') + ')')
610              },
611            0.012)
612          })
613
614          $(window).on("mouseup", function(e) {
615            if (resizing !== null) {
616              clearInterval(resizing)
617            }
618          })
619
620        }
621      })
622      $childIsChildInput.filter(':has(input[type=radio])').addClass('is-radio')
623      $childIsChildInput.filter(':has(input[type=checkbox])').addClass('is-checkbox').each(function(){
624        if ($(this).children('label').length === 0) {
625          $(this).addClass('no-label')
626        }
627      })
628      $this.is('.form-validator--help-effect') && $childFormGroup.find('.help-block').wrapInner("<div class='help-block__text'></div>") && $childFormGroup.find('.help-block:not(".with-errors")').addClass('is-normal');
629
630    })
631  }
632
633  var old = $.fn.validator
634
635  $.fn.validator             = Plugin
636  $.fn.validator.Constructor = Validator
637
638
639  // VALIDATOR NO CONFLICT
640  // =====================
641
642  $.fn.validator.noConflict = function () {
643    $.fn.validator = old
644    return this
645  }
646
647
648  // VALIDATOR DATA-API
649  // ==================
650  window.validator = {}
651  $(window).on('load', function () {
652    if (typeof $.initialize == 'function'){
653      $.initialize('form', function() {
654        var $form = $(this)
655        $form.attr('data-validate') !== 'false' && $form.attr('data-toggle', 'validator').addClass('form-validator')
656        Plugin.call($form, $form.data())
657      });
658    } else {
659      $('form').each(function () {
660        var $form = $(this)
661        $form.attr('data-validate') !== 'false' && $form.attr('data-toggle', 'validator').addClass('form-validator')
662        Plugin.call($form, $form.data())
663      })
664    }
665
666    $('body').delegate('form input, form select, form textarea', 'focus', function(){
667      $(this).parents(".form-group").addClass('is-focus')
668    });
669    $('body').delegate('form input, form select, form textarea', 'blur', function(){
670      var formGroup = $(this).parents(".form-group")
671
672      $(this).is(':not(select)') &&
673      formGroup[getValue($(this)) ? "addClass" : "removeClass"]('is-filled') &&
674      formGroup.is('.is-child')
675      formGroup.parents('.form-group')[formGroup.parents('.form-group').is(':has(.is-filled)') ? "addClass" : "removeClass"]('is-filled')
676
677      formGroup.removeClass('is-focus')
678    });
679    $('body').delegate('form input[type=checkbox], form select, form input[type=radio]', 'change', function(){
680      var formGroup = $(this).parents(".form-group")
681      formGroup[getValue($(this)) ? "addClass" : "removeClass"]('is-filled')
682      formGroup.is('.is-child') &&
683      formGroup.parents('.form-group')[getValue($(this)) ? "addClass" : "removeClass"]('is-filled')
684
685      formGroup.removeClass('is-focus')
686    });
687    $('input[type=text][value]').trigger('blur')
688
689    // $('select:has(option:selected)').trigger('change')
690    $("select").each(function() {
691        if ($(this).data("trigger") !== "static") {
692          $(this).trigger('change');
693        }
694    });
695
696    $('textarea').filter(function () {
697        return $(this).val();
698    }).trigger('blur')
699  })
700
701}(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.