<commit_before>/* ========================================================================
 * Bootstrap (plugin): validator.js v0.10.2
 * ========================================================================
 * 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
  // ==========================

  function getValue($el) {
    return $el.is('[type="checkbox"]') ? $el.prop('checked')                                     :
           $el.is('[type="radio"]')    ? !!$('[name="' + $el.attr('name') + '"]:checked').length :
                                         $el.val()
  }

  var Validator = function (element, options) {
    this.options  = options
    this.$element = $(element)
    this.$inputs  = this.$element.find(Validator.INPUT_SELECTOR)
    this.$btn     = $('button[type="submit"], input[type="submit"]')
                      .filter('[form="' + this.$element.attr('id') + '"]')
                      .add(this.$element.find('input[type="submit"], button[type="submit"]'))

    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.on('input.bs.validator change.bs.validator focusout.bs.validator', Validator.INPUT_SELECTOR, $.proxy(this.onInput, 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) {
        getValue($this) && $this.trigger('input.bs.validator')
      })
    })

    this.$inputs.filter(function () { return this.value !== "" }).trigger('focusout')

    this.$element.attr('novalidate', true) // disable automatic native validation
    this.toggleSubmit()
  }

  Validator.VERSION = '0.10.2'

  Validator.INPUT_SELECTOR = ':input:not([type="submit"], button):enabled:visible'

  Validator.FOCUS_OFFSET = 20

  Validator.DEFAULTS = {
    delay: 500,
    html: false,
    disable: true,
    focus: 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]
      if (!el.checkValidity) return true
      return el.validity.valid
    },
    '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.onInput = function (e) {
    var self        = this
    var $el         = $(e.target)
    var deferErrors = e.type !== 'focusout'
    this.validateInput($el, deferErrors).done(function () {
      self.toggleSubmit()
    })
  }

  Validator.prototype.validateInput = function ($el, deferErrors) {
    var value      = getValue($el)
    var prevValue  = $el.data('bs.validator.previous')
    var prevErrors = $el.data('bs.validator.errors')
    var errors

    if (prevValue === value) return $.Deferred().resolve()
    else $el.data('bs.validator.previous', value)

    if ($el.is('[type="radio"]')) $el = this.$element.find('input[name="' + $el.attr('name') + '"]')

    var e = $.Event('validate.bs.validator', {relatedTarget: $el[0]})
    this.$element.trigger(e)
    if (e.isDefaultPrevented()) return

    var self = this

    return this.runValidators($el).done(function (errors) {
      $el.data('bs.validator.errors', errors)

      errors.length
        ? deferErrors ? self.defer($el, self.showErrors) : 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 ((getValue($el) || $el.attr('required')) &&
          ($el.data(key) || key == 'native') &&
          !validator.call(this, $el)) {
        var error = getErrorMessage(key)
        !~errors.indexOf(error) && errors.push(error)
      }
    }, this))

    if (!errors.length && getValue($el) && $el.data('remote')) {
      this.defer($el, function () {
        var data = {}
        data[$el.attr('name')] = getValue($el)
        $.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 self = this

    $.when(this.$inputs.map(function (el) {
      return self.validateInput($(this), false)
    })).then(function () {
      self.toggleSubmit()
      self.focusError()
    })

    return this
  }

  Validator.prototype.focusError = function () {
    if (!this.options.focus) return

    var $input = $(".has-error:first :input")
    if ($input.length === 0) return

    $('html, body').animate({scrollTop: $input.offset().top - Validator.FOCUS_OFFSET}, 250)
    $input.focus()
  }

  Validator.prototype.showErrors = function ($el) {
    var method = this.options.html ? 'html' : 'text'
    var errors = $el.data('bs.validator.errors')
    var $group = $el.closest('.form-group')
    var $block = $group.find('.help-block.with-errors')
    var $feedback = $group.find('.form-control-feedback')

    if (!errors.length) return

    errors = $('<ul/>')
      .addClass('list-unstyled')
      .append($.map(errors, function (error) { return $('<li/>')[method](error) }))

    $block.data('bs.validator.originalContent') === undefined && $block.data('bs.validator.originalContent', $block.html())
    $block.empty().append(errors)
    $group.addClass('has-error has-danger')

    $group.hasClass('has-feedback')
      && $feedback.removeClass(this.options.feedback.success)
      && $feedback.addClass(this.options.feedback.error)
      && $group.removeClass('has-success')
  }

  Validator.prototype.clearErrors = function ($el) {
    var $group = $el.closest('.form-group')
    var $block = $group.find('.help-block.with-errors')
    var $feedback = $group.find('.form-control-feedback')

    $block.html($block.data('bs.validator.originalContent'))
    $group.removeClass('has-error has-danger')

    $group.hasClass('has-feedback')
      && $feedback.removeClass(this.options.feedback.error)
      && getValue($el)
      && $feedback.addClass(this.options.feedback.success)
      && $group.addClass('has-success')
  }

  Validator.prototype.hasErrors = function () {
    function fieldErrors() {
      return !!($(this).data('bs.validator.errors') || []).length
    }

    return !!this.$inputs.filter(fieldErrors).length
  }

  Validator.prototype.isIncomplete = function () {
    function fieldIncomplete() {
      var value = getValue($(this))
      return !(typeof value == "string" ? $.trim(value) : value)
    }

    return !!this.$inputs.filter('[required]').filter(fieldIncomplete).length
  }

  Validator.prototype.onSubmit = function (e) {
    this.validate()
    if (this.isIncomplete() || this.hasErrors()) e.preventDefault()
  }

  Validator.prototype.toggleSubmit = function () {
    if (!this.options.disable) return
    this.$btn.toggleClass('disabled', this.isIncomplete() || this.hasErrors())
  }

  Validator.prototype.defer = function ($el, callback) {
    callback = $.proxy(callback, this, $el)
    if (!this.options.delay) return callback()
    window.clearTimeout($el.data('bs.validator.timeout'))
    $el.data('bs.validator.timeout', window.setTimeout(callback, this.options.delay))
  }

  Validator.prototype.destroy = function () {
    this.$element
      .removeAttr('novalidate')
      .removeData('bs.validator')
      .off('.bs.validator')
      .find('.form-control-feedback')
        .removeClass([this.options.feedback.error, this.options.feedback.success].join(' '))

    this.$inputs
      .off('.bs.validator')
      .removeData(['bs.validator.errors', 'bs.validator.deferred', 'bs.validator.previous'])
      .each(function () {
        var $this = $(this)
        var timeout = $this.data('bs.validator.timeout')
        window.clearTimeout(timeout) && $this.removeData('bs.validator.timeout')
      })

    this.$element.find('.help-block.with-errors').each(function () {
      var $this = $(this)
      var originalContent = $this.data('bs.validator.originalContent')

      $this
        .removeData('bs.validator.originalContent')
        .html(originalContent)
    })

    this.$element.find('input[type="submit"], button[type="submit"]').removeClass('disabled')

    this.$element.find('.has-error, .has-danger').removeClass('has-error has-danger')

    return this
  }

  // VALIDATOR PLUGIN DEFINITION
  // ===========================

  function Plugin(option) {
    return this.each(function () {
      var $this   = $(this)
      var options = $.extend({}, Validator.DEFAULTS, $this.data(), typeof option == 'object' && option)
      var data    = $this.data('bs.validator')

      if (!data && option == 'destroy') return
      if (!data) $this.data('bs.validator', (data = new Validator(this, options)))
      if (typeof option == 'string') data[option]()
    })
  }

  var old = $.fn.validator

  $.fn.validator             = Plugin
  $.fn.validator.Constructor = Validator

  // VALIDATOR NO CONFLICT
  // =====================

  $.fn.validator.noConflict = function () {
    $.fn.validator = old
    return this
  }

  // VALIDATOR DATA-API
  // ==================

  $(window).on('load', function () {
    $('form[data-toggle="validator"]').each(function () {
      var $form = $(this)
      Plugin.call($form, $form.data())
    })
  })

}(jQuery);
<commit_msg>Removing (value == previousValue => skip) optimization. It was breaking the match validator and wasn’t really providing much perf gains. Fixes #316. Fixes #340.<commit_after>/* ========================================================================
 * Bootstrap (plugin): validator.js v0.10.2
 * ========================================================================
 * 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
  // ==========================

  function getValue($el) {
    return $el.is('[type="checkbox"]') ? $el.prop('checked')                                     :
           $el.is('[type="radio"]')    ? !!$('[name="' + $el.attr('name') + '"]:checked').length :
                                         $el.val()
  }

  var Validator = function (element, options) {
    this.options  = options
    this.$element = $(element)
    this.$inputs  = this.$element.find(Validator.INPUT_SELECTOR)
    this.$btn     = $('button[type="submit"], input[type="submit"]')
                      .filter('[form="' + this.$element.attr('id') + '"]')
                      .add(this.$element.find('input[type="submit"], button[type="submit"]'))

    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.on('input.bs.validator change.bs.validator focusout.bs.validator', Validator.INPUT_SELECTOR, $.proxy(this.onInput, 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) {
        getValue($this) && $this.trigger('input.bs.validator')
      })
    })

    this.$inputs.filter(function () { return this.value !== "" }).trigger('focusout')

    this.$element.attr('novalidate', true) // disable automatic native validation
    this.toggleSubmit()
  }

  Validator.VERSION = '0.10.2'

  Validator.INPUT_SELECTOR = ':input:not([type="submit"], button):enabled:visible'

  Validator.FOCUS_OFFSET = 20

  Validator.DEFAULTS = {
    delay: 500,
    html: false,
    disable: true,
    focus: 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]
      if (!el.checkValidity) return true
      return el.validity.valid
    },
    '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.onInput = function (e) {
    var self        = this
    var $el         = $(e.target)
    var deferErrors = e.type !== 'focusout'
    this.validateInput($el, deferErrors).done(function () {
      self.toggleSubmit()
    })
  }

  Validator.prototype.validateInput = function ($el, deferErrors) {
    var value      = getValue($el)
    var prevErrors = $el.data('bs.validator.errors')
    var errors

    if ($el.is('[type="radio"]')) $el = this.$element.find('input[name="' + $el.attr('name') + '"]')

    var e = $.Event('validate.bs.validator', {relatedTarget: $el[0]})
    this.$element.trigger(e)
    if (e.isDefaultPrevented()) return

    var self = this

    return this.runValidators($el).done(function (errors) {
      $el.data('bs.validator.errors', errors)

      errors.length
        ? deferErrors ? self.defer($el, self.showErrors) : 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 ((getValue($el) || $el.attr('required')) &&
          ($el.data(key) || key == 'native') &&
          !validator.call(this, $el)) {
        var error = getErrorMessage(key)
        !~errors.indexOf(error) && errors.push(error)
      }
    }, this))

    if (!errors.length && getValue($el) && $el.data('remote')) {
      this.defer($el, function () {
        var data = {}
        data[$el.attr('name')] = getValue($el)
        $.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 self = this

    $.when(this.$inputs.map(function (el) {
      return self.validateInput($(this), false)
    })).then(function () {
      self.toggleSubmit()
      self.focusError()
    })

    return this
  }

  Validator.prototype.focusError = function () {
    if (!this.options.focus) return

    var $input = $(".has-error:first :input")
    if ($input.length === 0) return

    $('html, body').animate({scrollTop: $input.offset().top - Validator.FOCUS_OFFSET}, 250)
    $input.focus()
  }

  Validator.prototype.showErrors = function ($el) {
    var method = this.options.html ? 'html' : 'text'
    var errors = $el.data('bs.validator.errors')
    var $group = $el.closest('.form-group')
    var $block = $group.find('.help-block.with-errors')
    var $feedback = $group.find('.form-control-feedback')

    if (!errors.length) return

    errors = $('<ul/>')
      .addClass('list-unstyled')
      .append($.map(errors, function (error) { return $('<li/>')[method](error) }))

    $block.data('bs.validator.originalContent') === undefined && $block.data('bs.validator.originalContent', $block.html())
    $block.empty().append(errors)
    $group.addClass('has-error has-danger')

    $group.hasClass('has-feedback')
      && $feedback.removeClass(this.options.feedback.success)
      && $feedback.addClass(this.options.feedback.error)
      && $group.removeClass('has-success')
  }

  Validator.prototype.clearErrors = function ($el) {
    var $group = $el.closest('.form-group')
    var $block = $group.find('.help-block.with-errors')
    var $feedback = $group.find('.form-control-feedback')

    $block.html($block.data('bs.validator.originalContent'))
    $group.removeClass('has-error has-danger')

    $group.hasClass('has-feedback')
      && $feedback.removeClass(this.options.feedback.error)
      && getValue($el)
      && $feedback.addClass(this.options.feedback.success)
      && $group.addClass('has-success')
  }

  Validator.prototype.hasErrors = function () {
    function fieldErrors() {
      return !!($(this).data('bs.validator.errors') || []).length
    }

    return !!this.$inputs.filter(fieldErrors).length
  }

  Validator.prototype.isIncomplete = function () {
    function fieldIncomplete() {
      var value = getValue($(this))
      return !(typeof value == "string" ? $.trim(value) : value)
    }

    return !!this.$inputs.filter('[required]').filter(fieldIncomplete).length
  }

  Validator.prototype.onSubmit = function (e) {
    this.validate()
    if (this.isIncomplete() || this.hasErrors()) e.preventDefault()
  }

  Validator.prototype.toggleSubmit = function () {
    if (!this.options.disable) return
    this.$btn.toggleClass('disabled', this.isIncomplete() || this.hasErrors())
  }

  Validator.prototype.defer = function ($el, callback) {
    callback = $.proxy(callback, this, $el)
    if (!this.options.delay) return callback()
    window.clearTimeout($el.data('bs.validator.timeout'))
    $el.data('bs.validator.timeout', window.setTimeout(callback, this.options.delay))
  }

  Validator.prototype.destroy = function () {
    this.$element
      .removeAttr('novalidate')
      .removeData('bs.validator')
      .off('.bs.validator')
      .find('.form-control-feedback')
        .removeClass([this.options.feedback.error, this.options.feedback.success].join(' '))

    this.$inputs
      .off('.bs.validator')
      .removeData(['bs.validator.errors', 'bs.validator.deferred'])
      .each(function () {
        var $this = $(this)
        var timeout = $this.data('bs.validator.timeout')
        window.clearTimeout(timeout) && $this.removeData('bs.validator.timeout')
      })

    this.$element.find('.help-block.with-errors').each(function () {
      var $this = $(this)
      var originalContent = $this.data('bs.validator.originalContent')

      $this
        .removeData('bs.validator.originalContent')
        .html(originalContent)
    })

    this.$element.find('input[type="submit"], button[type="submit"]').removeClass('disabled')

    this.$element.find('.has-error, .has-danger').removeClass('has-error has-danger')

    return this
  }

  // VALIDATOR PLUGIN DEFINITION
  // ===========================

  function Plugin(option) {
    return this.each(function () {
      var $this   = $(this)
      var options = $.extend({}, Validator.DEFAULTS, $this.data(), typeof option == 'object' && option)
      var data    = $this.data('bs.validator')

      if (!data && option == 'destroy') return
      if (!data) $this.data('bs.validator', (data = new Validator(this, options)))
      if (typeof option == 'string') data[option]()
    })
  }

  var old = $.fn.validator

  $.fn.validator             = Plugin
  $.fn.validator.Constructor = Validator

  // VALIDATOR NO CONFLICT
  // =====================

  $.fn.validator.noConflict = function () {
    $.fn.validator = old
    return this
  }

  // VALIDATOR DATA-API
  // ==================

  $(window).on('load', function () {
    $('form[data-toggle="validator"]').each(function () {
      var $form = $(this)
      Plugin.call($form, $form.data())
    })
  })

}(jQuery);
<|endoftext|>


<commit_before>module.exports = {
  rules: {
    'accessor-pairs': ['error', {
      getWithoutSet: true
    }],
    'array-callback-return': 'error',
    'block-scoped-var': 'error',
    'class-methods-use-this': 'off',
    'complexity': ['error', 5],
    'consistent-return': 'error',
    'curly': ['error', 'all'],
    'dot-location': ['error', 'property'],
    'dot-notation': 'error',
    'eqeqeq': ['error', 'always'],
    'guard-for-in': 'error',
    'no-alert': 'error',
    'no-caller': 'error',
    'no-case-declarations': 'error',
    'no-div-regex': 'error',
    'no-else-return': 'error',
    'no-empty-function': ['error', {
      allow: ['arrowFunctions']
    }],
    'no-empty-pattern': 'error',
    'no-eq-null': 'error',
    'no-eval': 'error',
    'no-extend-native': 'error',
    'no-extra-bind': 'error',
    'no-fallthrough': 'error',
    'no-floating-decimal': 'error',
    'no-global-assign': 'error',
    'no-implicit-globals': 'error',
    'no-implied-eval': 'error',
    'no-invalid-this': 'error',
    'no-iterator': 'error',
    'no-labels': 'error',
    'no-lone-blocks': 'error',
    'no-loop-func': 'error',
    'no-magic-numbers': ['error', {
      enforceConst: true,
      detectObjects: true,
      ignore: [-1, 0, 1, 2, 3, 4, 5]
    }],
    'no-multi-spaces': ['error', {
      exceptions: {
        Property: false,
        BinaryExpression: false,
        VariableDeclarator: false,
        ImportDeclaration: false
      }
    }],
    'no-multi-str': 'error',
    'no-new': 'error',
    'no-new-func': 'error',
    'no-new-wrappers': 'error',
    'no-octal': 'error',
    'no-octal-escape': 'error',
    'no-param-reassign': ['error', {
      props: true
    }],
    'no-proto': 'error',
    'no-redeclare': ['error', {
      builtinGlobals: true
    }],
    'no-return-assign': ['error', 'always'],
    'no-return-await': 'error',
    'no-script-url': 'error',
    'no-self-assign': ['error', {
      props: true
    }],
    'no-self-compare': 'error',
    'no-sequences': 'error',
    'no-throw-literal': 'error',
    'no-unmodified-loop-condition': 'error',
    'no-unused-expressions': 'error',
    'no-useless-call': 'error',
    'no-useless-concat': 'error',
    'no-useless-escape': 'error',
    'no-useless-return': 'error',
    'no-void': 'error',
    'no-warning-comments': 'error',
    'no-with': 'error',
    'prefer-promise-reject-errors': 'error',
    'radix': ['error', 'as-needed'],
    'require-await': 'error',
    'vars-on-top': 'error',
    'wrap-iife': ['error', 'outside', {
      functionPrototypeMethods: true
    }],
    'yoda': ['error', 'never']
  }
};
<commit_msg>Turn off magic numbers<commit_after>module.exports = {
  rules: {
    'accessor-pairs': ['error', {
      getWithoutSet: true
    }],
    'array-callback-return': 'error',
    'block-scoped-var': 'error',
    'class-methods-use-this': 'off',
    'complexity': ['error', 5],
    'consistent-return': 'error',
    'curly': ['error', 'all'],
    'dot-location': ['error', 'property'],
    'dot-notation': 'error',
    'eqeqeq': ['error', 'always'],
    'guard-for-in': 'error',
    'no-alert': 'error',
    'no-caller': 'error',
    'no-case-declarations': 'error',
    'no-div-regex': 'error',
    'no-else-return': 'error',
    'no-empty-function': ['error', {
      allow: ['arrowFunctions']
    }],
    'no-empty-pattern': 'error',
    'no-eq-null': 'error',
    'no-eval': 'error',
    'no-extend-native': 'error',
    'no-extra-bind': 'error',
    'no-fallthrough': 'error',
    'no-floating-decimal': 'error',
    'no-global-assign': 'error',
    'no-implicit-globals': 'error',
    'no-implied-eval': 'error',
    'no-invalid-this': 'error',
    'no-iterator': 'error',
    'no-labels': 'error',
    'no-lone-blocks': 'error',
    'no-loop-func': 'error',
    'no-magic-numbers': 'off',
    'no-multi-spaces': ['error', {
      exceptions: {
        Property: false,
        BinaryExpression: false,
        VariableDeclarator: false,
        ImportDeclaration: false
      }
    }],
    'no-multi-str': 'error',
    'no-new': 'error',
    'no-new-func': 'error',
    'no-new-wrappers': 'error',
    'no-octal': 'error',
    'no-octal-escape': 'error',
    'no-param-reassign': ['error', {
      props: true
    }],
    'no-proto': 'error',
    'no-redeclare': ['error', {
      builtinGlobals: true
    }],
    'no-return-assign': ['error', 'always'],
    'no-return-await': 'error',
    'no-script-url': 'error',
    'no-self-assign': ['error', {
      props: true
    }],
    'no-self-compare': 'error',
    'no-sequences': 'error',
    'no-throw-literal': 'error',
    'no-unmodified-loop-condition': 'error',
    'no-unused-expressions': 'error',
    'no-useless-call': 'error',
    'no-useless-concat': 'error',
    'no-useless-escape': 'error',
    'no-useless-return': 'error',
    'no-void': 'error',
    'no-warning-comments': 'error',
    'no-with': 'error',
    'prefer-promise-reject-errors': 'error',
    'radix': ['error', 'as-needed'],
    'require-await': 'error',
    'vars-on-top': 'error',
    'wrap-iife': ['error', 'outside', {
      functionPrototypeMethods: true
    }],
    'yoda': ['error', 'never']
  }
};
<|endoftext|>


<commit_before>/* ========================================================================
 * 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 eventType  = e.type
    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
        ? eventType == 'focusout' ? self.showErrors($el) : self.defer($el, self.showErrors)
        : 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'
    var errors = $el.data('bs.validator.errors')
    var $group = $el.closest('.form-group')
    var $block = $group.find('.help-block.with-errors')
    var $feedback = $group.find('.form-control-feedback')

    if (!errors.length) return

    errors = $('<ul/>')
      .addClass('list-unstyled')
      .append($.map(errors, function (error) { return $('<li/>')[method](error) }))

    $block.data('bs.validator.originalContent') === undefined && $block.data('bs.validator.originalContent', $block.html())
    $block.empty().append(errors)
    $group.addClass('has-error')

    $group.hasClass('has-feedback')
      && $feedback.removeClass(this.options.feedback.success)
      && $feedback.addClass(this.options.feedback.error)
      && $group.removeClass('has-success')
  }

  Validator.prototype.clearErrors = function ($el) {
    var $group = $el.closest('.form-group')
    var $block = $group.find('.help-block.with-errors')
    var $feedback = $group.find('.form-control-feedback')

    $block.html($block.data('bs.validator.originalContent'))
    $group.removeClass('has-error')

    $group.hasClass('has-feedback')
      && $feedback.removeClass(this.options.feedback.error)
      && $el.val()
      && $feedback.addClass(this.options.feedback.success)
      && $group.addClass('has-success')
  }

  Validator.prototype.hasErrors = function () {
    function fieldErrors() {
      return !!($(this).data('bs.validator.errors') || []).length
    }

    return !!this.$element.find(Validator.INPUT_SELECTOR).filter(fieldErrors).length
  }

  Validator.prototype.isIncomplete = function () {
    function fieldIncomplete() {
      return this.type === 'checkbox' ? !this.checked                                   :
             this.type === 'radio'    ? !$('[name="' + this.name + '"]:checked').length :
                                        $.trim(this.value) === ''
    }

    return !!this.$element.find(Validator.INPUT_SELECTOR).filter('[required]').filter(fieldIncomplete).length
  }

  Validator.prototype.onSubmit = function (e) {
    this.validate()
    if (this.isIncomplete() || this.hasErrors()) e.preventDefault()
  }

  Validator.prototype.toggleSubmit = function () {
    if(!this.options.disable) return

    var $btn = $('button[type="submit"], input[type="submit"]')
      .filter('[form="' + this.$element.attr('id') + '"]')
      .add(this.$element.find('input[type="submit"], button[type="submit"]'))

    $btn.toggleClass('disabled', this.isIncomplete() || this.hasErrors())
  }

  Validator.prototype.defer = function ($el, callback) {
    callback = $.proxy(callback, this, $el)
    if (!this.options.delay) return callback()
    window.clearTimeout($el.data('bs.validator.timeout'))
    $el.data('bs.validator.timeout', window.setTimeout(callback, this.options.delay))
  }

  Validator.prototype.destroy = function () {
    this.$element
      .removeAttr('novalidate')
      .removeData('bs.validator')
      .off('.bs.validator')
      .find('.form-control-feedback')
        .removeClass([this.options.feedback.error, this.options.feedback.success].join(' '))

    this.$element.find(Validator.INPUT_SELECTOR)
      .off('.bs.validator')
      .removeData(['bs.validator.errors', 'bs.validator.deferred'])
      .each(function () {
        var $this = $(this)
        var timeout = $this.data('bs.validator.timeout')
        window.clearTimeout(timeout) && $this.removeData('bs.validator.timeout')
      })

    this.$element.find('.help-block.with-errors').each(function () {
      var $this = $(this)
      var originalContent = $this.data('bs.validator.originalContent')

      $this
        .removeData('bs.validator.originalContent')
        .html(originalContent)
    })

    this.$element.find('input[type="submit"], button[type="submit"]').removeClass('disabled')

    this.$element.find('.has-error').removeClass('has-error')

    return this
  }

  // VALIDATOR PLUGIN DEFINITION
  // ===========================

  function Plugin(option) {
    return this.each(function () {
      var $this   = $(this)
      var options = $.extend({}, Validator.DEFAULTS, $this.data(), typeof option == 'object' && option)
      var data    = $this.data('bs.validator')

      if (!data && option == 'destroy') return
      if (!data) $this.data('bs.validator', (data = new Validator(this, options)))
      if (typeof option == 'string') data[option]()
    })
  }

  var old = $.fn.validator

  $.fn.validator             = Plugin
  $.fn.validator.Constructor = Validator

  // VALIDATOR NO CONFLICT
  // =====================

  $.fn.validator.noConflict = function () {
    $.fn.validator = old
    return this
  }

  // VALIDATOR DATA-API
  // ==================

  $(window).on('load', function () {
    $('form[data-toggle="validator"]').each(function () {
      var $form = $(this)
      Plugin.call($form, $form.data())
    })
  })

}(jQuery);
<commit_msg>Adding compatibility with Bootstrap 4 via .has-danger class. Fixes #271<commit_after>/* ========================================================================
 * 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 eventType  = e.type
    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
        ? eventType == 'focusout' ? self.showErrors($el) : self.defer($el, self.showErrors)
        : 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'
    var errors = $el.data('bs.validator.errors')
    var $group = $el.closest('.form-group')
    var $block = $group.find('.help-block.with-errors')
    var $feedback = $group.find('.form-control-feedback')

    if (!errors.length) return

    errors = $('<ul/>')
      .addClass('list-unstyled')
      .append($.map(errors, function (error) { return $('<li/>')[method](error) }))

    $block.data('bs.validator.originalContent') === undefined && $block.data('bs.validator.originalContent', $block.html())
    $block.empty().append(errors)
    $group.addClass('has-error has-danger')

    $group.hasClass('has-feedback')
      && $feedback.removeClass(this.options.feedback.success)
      && $feedback.addClass(this.options.feedback.error)
      && $group.removeClass('has-success')
  }

  Validator.prototype.clearErrors = function ($el) {
    var $group = $el.closest('.form-group')
    var $block = $group.find('.help-block.with-errors')
    var $feedback = $group.find('.form-control-feedback')

    $block.html($block.data('bs.validator.originalContent'))
    $group.removeClass('has-error has-danger')

    $group.hasClass('has-feedback')
      && $feedback.removeClass(this.options.feedback.error)
      && $el.val()
      && $feedback.addClass(this.options.feedback.success)
      && $group.addClass('has-success')
  }

  Validator.prototype.hasErrors = function () {
    function fieldErrors() {
      return !!($(this).data('bs.validator.errors') || []).length
    }

    return !!this.$element.find(Validator.INPUT_SELECTOR).filter(fieldErrors).length
  }

  Validator.prototype.isIncomplete = function () {
    function fieldIncomplete() {
      return this.type === 'checkbox' ? !this.checked                                   :
             this.type === 'radio'    ? !$('[name="' + this.name + '"]:checked').length :
                                        $.trim(this.value) === ''
    }

    return !!this.$element.find(Validator.INPUT_SELECTOR).filter('[required]').filter(fieldIncomplete).length
  }

  Validator.prototype.onSubmit = function (e) {
    this.validate()
    if (this.isIncomplete() || this.hasErrors()) e.preventDefault()
  }

  Validator.prototype.toggleSubmit = function () {
    if(!this.options.disable) return

    var $btn = $('button[type="submit"], input[type="submit"]')
      .filter('[form="' + this.$element.attr('id') + '"]')
      .add(this.$element.find('input[type="submit"], button[type="submit"]'))

    $btn.toggleClass('disabled', this.isIncomplete() || this.hasErrors())
  }

  Validator.prototype.defer = function ($el, callback) {
    callback = $.proxy(callback, this, $el)
    if (!this.options.delay) return callback()
    window.clearTimeout($el.data('bs.validator.timeout'))
    $el.data('bs.validator.timeout', window.setTimeout(callback, this.options.delay))
  }

  Validator.prototype.destroy = function () {
    this.$element
      .removeAttr('novalidate')
      .removeData('bs.validator')
      .off('.bs.validator')
      .find('.form-control-feedback')
        .removeClass([this.options.feedback.error, this.options.feedback.success].join(' '))

    this.$element.find(Validator.INPUT_SELECTOR)
      .off('.bs.validator')
      .removeData(['bs.validator.errors', 'bs.validator.deferred'])
      .each(function () {
        var $this = $(this)
        var timeout = $this.data('bs.validator.timeout')
        window.clearTimeout(timeout) && $this.removeData('bs.validator.timeout')
      })

    this.$element.find('.help-block.with-errors').each(function () {
      var $this = $(this)
      var originalContent = $this.data('bs.validator.originalContent')

      $this
        .removeData('bs.validator.originalContent')
        .html(originalContent)
    })

    this.$element.find('input[type="submit"], button[type="submit"]').removeClass('disabled')

    this.$element.find('.has-error, .has-danger').removeClass('has-error has-danger')

    return this
  }

  // VALIDATOR PLUGIN DEFINITION
  // ===========================

  function Plugin(option) {
    return this.each(function () {
      var $this   = $(this)
      var options = $.extend({}, Validator.DEFAULTS, $this.data(), typeof option == 'object' && option)
      var data    = $this.data('bs.validator')

      if (!data && option == 'destroy') return
      if (!data) $this.data('bs.validator', (data = new Validator(this, options)))
      if (typeof option == 'string') data[option]()
    })
  }

  var old = $.fn.validator

  $.fn.validator             = Plugin
  $.fn.validator.Constructor = Validator

  // VALIDATOR NO CONFLICT
  // =====================

  $.fn.validator.noConflict = function () {
    $.fn.validator = old
    return this
  }

  // VALIDATOR DATA-API
  // ==================

  $(window).on('load', function () {
    $('form[data-toggle="validator"]').each(function () {
      var $form = $(this)
      Plugin.call($form, $form.data())
    })
  })

}(jQuery);
<|endoftext|>


<commit_before>// Universal Subtitles, universalsubtitles.org
//
// Copyright (C) 2010 Participatory Culture Foundation
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see
// http://www.gnu.org/licenses/agpl-3.0.html.

goog.provide('mirosubs.subtitle.BottomFinishedPanel');

mirosubs.subtitle.BottomFinishedPanel = function(dialog) {
    goog.ui.Component.call(this);
    this.dialog_ = dialog;
};
goog.inherits(mirosubs.subtitle.BottomFinishedPanel, goog.ui.Component);

mirosubs.subtitle.BottomFinishedPanel.prototype.createDom = function() {
    mirosubs.subtitle.BottomFinishedPanel.superClass_.createDom.call(this);
    this.getElement().className = 'mirosubs-translating';
    var $d = goog.bind(this.getDomHelper().createDom, this.getDomHelper());
    var attrs = {'className': 'mirosubs-done', 'href':'#'};
    this.addTranslationLink_ = $d('a', attrs, 'Add a Translation Now');
    this.askAFriendLink_ = $d('a', attrs, 'Ask a Friend to Translate');
    this.getElement().appendChild(
        $d('div', 'mirosubs-buttons',
           this.addTranslationLink_,
           this.askAFriendLink_));
    this.getElement().appendChild(
        $d('p', null,
           ['Your subtitles are now ready to be translated -- by you ',
            'and by others.  The best way to get translation help is ',
            'to reach out to your friends or people in your community ',
            'or orgnization.'].join('')));
    this.getElement().appendChild(
        $d('p', null,
           ["Do you know someone who speaks a language that you’d like ",
            "to translate into?"].join('')));
};
mirosubs.subtitle.BottomFinishedPanel.prototype.enterDocument = function() {
    mirosubs.subtitle.BottomFinishedPanel.superClass_.enterDocument.call(this);
    this.getHandler().listen(this.addTranslationLink_, 'click',
                             this.addTranslationClicked_);
    this.getHandler().listen(this.askAFriendLink_, 'click',
                             this.askAFriendClicked_);
};
mirosubs.subtitle.BottomFinishedPanel.prototype.addTranslationClicked_ =
    function(event)
{
    this.dialog_.addTranslationsAndClose();
    event.preventDefault();
};
mirosubs.subtitle.BottomFinishedPanel.prototype.askAFriendClicked_ =
    function(event)
{
    alert('stub: ask a friend clicked');
    event.preventDefault();
};<commit_msg>Changes 'not implemented yet' message' for 'ask a friend to translate' button. http://bugzilla.pculture.org/show_bug.cgi?id=13744<commit_after>// Universal Subtitles, universalsubtitles.org
//
// Copyright (C) 2010 Participatory Culture Foundation
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see
// http://www.gnu.org/licenses/agpl-3.0.html.

goog.provide('mirosubs.subtitle.BottomFinishedPanel');

mirosubs.subtitle.BottomFinishedPanel = function(dialog) {
    goog.ui.Component.call(this);
    this.dialog_ = dialog;
};
goog.inherits(mirosubs.subtitle.BottomFinishedPanel, goog.ui.Component);

mirosubs.subtitle.BottomFinishedPanel.prototype.createDom = function() {
    mirosubs.subtitle.BottomFinishedPanel.superClass_.createDom.call(this);
    this.getElement().className = 'mirosubs-translating';
    var $d = goog.bind(this.getDomHelper().createDom, this.getDomHelper());
    var attrs = {'className': 'mirosubs-done', 'href':'#'};
    this.addTranslationLink_ = $d('a', attrs, 'Add a Translation Now');
    this.askAFriendLink_ = $d('a', attrs, 'Ask a Friend to Translate');
    this.getElement().appendChild(
        $d('div', 'mirosubs-buttons',
           this.addTranslationLink_,
           this.askAFriendLink_));
    this.getElement().appendChild(
        $d('p', null,
           ['Your subtitles are now ready to be translated -- by you ',
            'and by others.  The best way to get translation help is ',
            'to reach out to your friends or people in your community ',
            'or orgnization.'].join('')));
    this.getElement().appendChild(
        $d('p', null,
           ["Do you know someone who speaks a language that you’d like ",
            "to translate into?"].join('')));
};
mirosubs.subtitle.BottomFinishedPanel.prototype.enterDocument = function() {
    mirosubs.subtitle.BottomFinishedPanel.superClass_.enterDocument.call(this);
    this.getHandler().listen(this.addTranslationLink_, 'click',
                             this.addTranslationClicked_);
    this.getHandler().listen(this.askAFriendLink_, 'click',
                             this.askAFriendClicked_);
};
mirosubs.subtitle.BottomFinishedPanel.prototype.addTranslationClicked_ =
    function(event)
{
    this.dialog_.addTranslationsAndClose();
    event.preventDefault();
};
mirosubs.subtitle.BottomFinishedPanel.prototype.askAFriendClicked_ =
    function(event)
{
    alert("Sorry.  We're still testing the widget, so we haven't enabled sharing features.  Please just email your friend a link for now.");
    event.preventDefault();
};<|endoftext|>


<commit_before>/* jshint asi:true */
//先等图片都加载完成
//再执行布局函数

/**
 * 执行主函数
 * @param  {[type]} function( [description]
 * @return {[type]}           [description]
 */
(function() {

    /**
     * 内容JSON
     */
    var demoContent = [{
        demo_link: 'http://gaohaoyang.github.io/test/headerTransition/',
        img_link: 'https://ooo.0o0.ooo/2016/06/20/5768c1597d1fe.png',
        code_link: 'https://github.com/Gaohaoyang/test/tree/master/headerTransition',
        title: 'Header Transition 渐变动画',
        core_tech: 'jQuery BootStrap CSS3',
        description: '花费不到半小时帮师兄做了一个简单的 CSS3 动画效果，当页面滚动到指定距离时，header 区的背景色由透明变为蓝色。仿照了网站 https://quorrajs.org/ 的 Header 区动画效果。'
    }, {
        demo_link: 'http://gaohaoyang.github.io/mask-fade-out/',
        img_link: 'http://7q5cdt.com1.z0.glb.clouddn.com/demo-fade-out.png',
        code_link: 'https://github.com/Gaohaoyang/mask-fade-out',
        title: '遮罩层按指定路径缩小消失',
        core_tech: 'jQuery CSS',
        description: '使用 animate 方法，做到兼容 IE8。曾在联想服务官网上线3个月。'
    }, {
        demo_link: 'http://gaohaoyang.github.io/ToDo-WebApp/',
        img_link: 'http://7q5cdt.com1.z0.glb.clouddn.com/blog-todoWebApp.png',
        code_link: 'https://github.com/Gaohaoyang/ToDo-WebApp',
        title: '百度前端学院 task0004 ToDo 应用(移动端)',
        core_tech: 'JavaScript LocalStorage requireJS Sass Gulp XSS',
        description: '在任务三中，做了一个 PC 端的 ToDo 应用。任务四是将它优化，以适应移动端设备。'
    }, {
        demo_link: 'http://gaohaoyang.github.io/baidu-ife-practice/task0003/',
        img_link: 'http://7q5cdt.com1.z0.glb.clouddn.com/demo-todo.png',
        code_link: 'https://github.com/Gaohaoyang/baidu-ife-practice/tree/master/task0003',
        title: '百度前端学院 task0003 ToDo 应用',
        core_tech: 'JavaScript LocalStorage',
        description: '任务三，ToDo 单页应用，主要使用了 LocalStorage 存储数据，使用 JSON 模拟了 3 张数据表。'
    }, {
        demo_link: 'http://gaohaoyang.github.io/ife/task/task0002/work/Gaohaoyang/task0002_5.html',
        img_link: 'http://7q5cdt.com1.z0.glb.clouddn.com/demo-drag.png',
        code_link: 'https://github.com/Gaohaoyang/ife/tree/master/task/task0002/work/Gaohaoyang',
        title: '拖拽交互',
        core_tech: 'JavaScript',
        description: '对鼠标事件应用，以及判断定位的方法等。'
    }, {
        demo_link: 'http://gaohaoyang.github.io/ife/task/task0002/work/Gaohaoyang/task0002_4.html',
        img_link: 'http://ww2.sinaimg.cn/large/7011d6cfjw1f3ba2krzs0j207005y0sv.jpg',
        code_link: 'https://github.com/Gaohaoyang/ife/tree/master/task/task0002/work/Gaohaoyang',
        title: '输入框即时提示',
        core_tech: 'JavaScript',
        description: '对input监听，使用正在表达式高亮匹配，实现输入联想效果。'
    }, {
        demo_link: 'http://gaohaoyang.github.io/ife/task/task0002/work/Gaohaoyang/task0002_3.html',
        img_link: 'http://ww2.sinaimg.cn/large/7011d6cfjw1f3ba04okoqj20eq093wh1.jpg',
        code_link: 'https://github.com/Gaohaoyang/ife/tree/master/task/task0002/work/Gaohaoyang',
        title: '轮播图',
        core_tech: 'JavaScript',
        description: '变速运动，运动终止条件的应用。'
    }, {
        demo_link: 'http://gaohaoyang.github.io/ife/task/task0002/work/Gaohaoyang/task0002_2.html',
        img_link: 'http://ww4.sinaimg.cn/large/7011d6cfjw1f3b9w6xpz5j20ae02pgm3.jpg',
        code_link: 'https://github.com/Gaohaoyang/ife/tree/master/task/task0002/work/Gaohaoyang',
        title: '倒计时',
        core_tech: 'JavaScript',
        description: 'setInterval()，Date 对象的学习和使用。'
    }, {
        demo_link: 'http://gaohaoyang.github.io/ife/task/task0002/work/Gaohaoyang/task0002_1.html',
        img_link: 'http://ww3.sinaimg.cn/large/7011d6cfjw1f3b9tmyuh2j20au0aaaar.jpg',
        code_link: 'https://github.com/Gaohaoyang/ife/tree/master/task/task0002/work/Gaohaoyang',
        title: '处理兴趣爱好列表',
        core_tech: 'JavaScript',
        description: '对JavaScript正则表达式和字符串的练习。'
    }, {
        demo_link: 'http://gaohaoyang.github.io/ife/task/task0002/work/Gaohaoyang/index.html',
        img_link: 'http://7q5cdt.com1.z0.glb.clouddn.com/demo-demo-index.png',
        code_link: 'https://github.com/Gaohaoyang/ife/tree/master/task/task0002/work/Gaohaoyang',
        title: '百度前端学院 task0002 展示主页',
        core_tech: 'HTML CSS',
        description: '任务二的展示主页，里面包含五个小 demo。还有一篇相关的日志。'
    }, {
        demo_link: 'http://gaohaoyang.github.io/ife/task/task0001/work/Gaohaoyang/index.html',
        img_link: 'http://7q5cdt.com1.z0.glb.clouddn.com/Demo-blog-ife.jpg',
        code_link: 'https://github.com/Gaohaoyang/ife/tree/master/task/task0001/work/Gaohaoyang',
        title: '百度前端学院 task0001 个人博客',
        core_tech: 'HTML CSS',
        description: '完成百度前端学院的任务。深刻的理解了BFC、浮动、inline-block间距，多列布局等技术。还有一篇相关的日志。'
    }, {
        demo_link: 'http://gaohaoyang.github.io/ghost-button-css3/',
        img_link: 'http://7q5cdt.com1.z0.glb.clouddn.com/DemoGhost-Button.png',
        code_link: 'https://github.com/Gaohaoyang/ghost-button-css3',
        title: 'Ghost Button 幽灵按钮',
        core_tech: 'CSS3',
        description: '使用 CSS3 中的旋转、缩放、过渡、动画等效果，制作出很酷的按钮效果。'
    }, {
        demo_link: 'http://gaohaoyang.github.io/shadow-demo-css3',
        img_link: 'http://7q5cdt.com1.z0.glb.clouddn.com/Demoshadow.png',
        code_link: 'https://github.com/Gaohaoyang/shadow-demo-css3',
        title: 'CSS3 阴影特效',
        core_tech: 'CSS3',
        description: 'CSS3 中的阴影、旋转等效果，制作出曲边阴影和翘边阴影。'
    }, {
        demo_link: 'http://gaohaoyang.github.io/learning-AngularJS/2-3-bookstore-add-sth-by-myself/',
        img_link: 'http://7q5cdt.com1.z0.glb.clouddn.com/DemoAngularJS.png',
        code_link: 'https://github.com/Gaohaoyang/learning-AngularJS/tree/master/2-3-bookstore-add-sth-by-myself',
        title: 'AngularJS 结合动画效果',
        core_tech: 'AngularJS CSS3',
        description: '使用 AngularJS 中的 ngAnimate 加 CSS3里面的一些旋转效果，做出页面切换的效果。'
    }, {
        demo_link: 'http://gaohaoyang.github.io/learning-AngularJS/2-4-UiRouterPractice',
        img_link: 'http://ww2.sinaimg.cn/large/7011d6cfjw1f3b8zumfqij20q40nh76x.jpg',
        code_link: 'https://github.com/Gaohaoyang/learning-AngularJS/tree/master/2-4-UiRouterPractice',
        title: 'AngularJS UI-router 练习',
        core_tech: 'AngularJS UI-router',
        description: 'UI-router 作为 AngularJS 中路由的扩充，实现了多级路由的效果。使得前端界面跳转更加方便。'
    }, {
        demo_link: 'http://gaohaoyang.github.io/test/bootstrap-zhihu/',
        img_link: 'http://7q5cdt.com1.z0.glb.clouddn.com/teach-girlfriend-html-CopyZhihu.jpg',
        code_link: 'https://github.com/Gaohaoyang/test/tree/master/bootstrap-zhihu',
        title: '仿知乎页面',
        core_tech: 'HTML BootStrap',
        description: '使用BootStrap仿照知乎做了一个静态页面。'
    }];

    contentInit(demoContent) //内容初始化
    waitImgsLoad() //等待图片加载，并执行布局初始化
}());

/**
 * 内容初始化
 * @return {[type]} [description]
 */
function contentInit(content) {
    // var htmlArr = [];
    // for (var i = 0; i < content.length; i++) {
    //     htmlArr.push('
')
    //     htmlArr.push('')
    //     htmlArr.push('')
    //     htmlArr.push('')
    //     htmlArr.push('
')
    //     htmlArr.push(''+content[i].title+'')
    //     htmlArr.push('
')
    //     htmlArr.push('
主要技术：'+content[i].core_tech+'
')
    //     htmlArr.push('
'+content[i].description)
    //     htmlArr.push('源代码 ')
    //     htmlArr.push('
')
    //     htmlArr.push('
')
    // }
    // var htmlStr = htmlArr.join('')
    var htmlStr = ''
    for (var i = 0; i < content.length; i++) {
        htmlStr +=
            '
' +
            '   ' +
            '       ' +
            '   ' +
            '
' +
            '       ' + content[i].title + '' +
            '
' +
            '
主要技术：' + content[i].core_tech + '
' +
            '
' + content[i].description +
            '       源代码 ' +
            '
' +
            '
'
    }
    var grid = document.querySelector('.grid')
    grid.insertAdjacentHTML('afterbegin', htmlStr)
}

/**
 * 等待图片加载
 * @return {[type]} [description]
 */
function waitImgsLoad() {
    var imgs = document.querySelectorAll('.grid img')
    var totalImgs = imgs.length
    var count = 0
        //console.log(imgs)
    for (var i = 0; i < totalImgs; i++) {
        if (imgs[i].complete) {
            //console.log('complete');
            count++
        } else {
            imgs[i].onload = function() {
                // alert('onload')
                count++
                //console.log('onload' + count)
                if (count == totalImgs) {
                    //console.log('onload---bbbbbbbb')
                    initGrid()
                }
            }
        }
    }
    if (count == totalImgs) {
        //console.log('---bbbbbbbb')
        initGrid()
    }
}

/**
 * 初始化栅格布局
 * @return {[type]} [description]
 */
function initGrid() {
    var msnry = new Masonry('.grid', {
        // options
        itemSelector: '.grid-item',
        columnWidth: 250,
        isFitWidth: true,
        gutter: 20,
    })
}
<commit_msg>button<commit_after>/* jshint asi:true */
//先等图片都加载完成
//再执行布局函数

/**
 * 执行主函数
 * @param  {[type]} function( [description]
 * @return {[type]}           [description]
 */
(function() {

    /**
     * 内容JSON
     */
    var demoContent = [
	{
        demo_link: 'https://github.com/liyoung1992/demo',
        img_link: 'https://ooo.0o0.ooo/2016/06/20/5768c1597d1fe.png',
        code_link: 'https://github.com/liyoung1992/demo/blob/master/buttonStyle.html',
        title: 'button样式',
        core_tech: 'Button Css',
        description: 'button样式，可以直接html，css，直接用；'
    }
	{
        demo_link: 'http://gaohaoyang.github.io/test/headerTransition/',
        img_link: 'https://ooo.0o0.ooo/2016/06/20/5768c1597d1fe.png',
        code_link: 'https://github.com/Gaohaoyang/test/tree/master/headerTransition',
        title: 'Header Transition 渐变动画',
        core_tech: 'jQuery BootStrap CSS3',
        description: '花费不到半小时帮师兄做了一个简单的 CSS3 动画效果，当页面滚动到指定距离时，header 区的背景色由透明变为蓝色。仿照了网站 https://quorrajs.org/ 的 Header 区动画效果。'
    }, {
        demo_link: 'http://gaohaoyang.github.io/mask-fade-out/',
        img_link: 'http://7q5cdt.com1.z0.glb.clouddn.com/demo-fade-out.png',
        code_link: 'https://github.com/Gaohaoyang/mask-fade-out',
        title: '遮罩层按指定路径缩小消失',
        core_tech: 'jQuery CSS',
        description: '使用 animate 方法，做到兼容 IE8。曾在联想服务官网上线3个月。'
    }, {
        demo_link: 'http://gaohaoyang.github.io/ToDo-WebApp/',
        img_link: 'http://7q5cdt.com1.z0.glb.clouddn.com/blog-todoWebApp.png',
        code_link: 'https://github.com/Gaohaoyang/ToDo-WebApp',
        title: '百度前端学院 task0004 ToDo 应用(移动端)',
        core_tech: 'JavaScript LocalStorage requireJS Sass Gulp XSS',
        description: '在任务三中，做了一个 PC 端的 ToDo 应用。任务四是将它优化，以适应移动端设备。'
    }, {
        demo_link: 'http://gaohaoyang.github.io/baidu-ife-practice/task0003/',
        img_link: 'http://7q5cdt.com1.z0.glb.clouddn.com/demo-todo.png',
        code_link: 'https://github.com/Gaohaoyang/baidu-ife-practice/tree/master/task0003',
        title: '百度前端学院 task0003 ToDo 应用',
        core_tech: 'JavaScript LocalStorage',
        description: '任务三，ToDo 单页应用，主要使用了 LocalStorage 存储数据，使用 JSON 模拟了 3 张数据表。'
    }, {
        demo_link: 'http://gaohaoyang.github.io/ife/task/task0002/work/Gaohaoyang/task0002_5.html',
        img_link: 'http://7q5cdt.com1.z0.glb.clouddn.com/demo-drag.png',
        code_link: 'https://github.com/Gaohaoyang/ife/tree/master/task/task0002/work/Gaohaoyang',
        title: '拖拽交互',
        core_tech: 'JavaScript',
        description: '对鼠标事件应用，以及判断定位的方法等。'
    }, {
        demo_link: 'http://gaohaoyang.github.io/ife/task/task0002/work/Gaohaoyang/task0002_4.html',
        img_link: 'http://ww2.sinaimg.cn/large/7011d6cfjw1f3ba2krzs0j207005y0sv.jpg',
        code_link: 'https://github.com/Gaohaoyang/ife/tree/master/task/task0002/work/Gaohaoyang',
        title: '输入框即时提示',
        core_tech: 'JavaScript',
        description: '对input监听，使用正在表达式高亮匹配，实现输入联想效果。'
    }, {
        demo_link: 'http://gaohaoyang.github.io/ife/task/task0002/work/Gaohaoyang/task0002_3.html',
        img_link: 'http://ww2.sinaimg.cn/large/7011d6cfjw1f3ba04okoqj20eq093wh1.jpg',
        code_link: 'https://github.com/Gaohaoyang/ife/tree/master/task/task0002/work/Gaohaoyang',
        title: '轮播图',
        core_tech: 'JavaScript',
        description: '变速运动，运动终止条件的应用。'
    }, {
        demo_link: 'http://gaohaoyang.github.io/ife/task/task0002/work/Gaohaoyang/task0002_2.html',
        img_link: 'http://ww4.sinaimg.cn/large/7011d6cfjw1f3b9w6xpz5j20ae02pgm3.jpg',
        code_link: 'https://github.com/Gaohaoyang/ife/tree/master/task/task0002/work/Gaohaoyang',
        title: '倒计时',
        core_tech: 'JavaScript',
        description: 'setInterval()，Date 对象的学习和使用。'
    }, {
        demo_link: 'http://gaohaoyang.github.io/ife/task/task0002/work/Gaohaoyang/task0002_1.html',
        img_link: 'http://ww3.sinaimg.cn/large/7011d6cfjw1f3b9tmyuh2j20au0aaaar.jpg',
        code_link: 'https://github.com/Gaohaoyang/ife/tree/master/task/task0002/work/Gaohaoyang',
        title: '处理兴趣爱好列表',
        core_tech: 'JavaScript',
        description: '对JavaScript正则表达式和字符串的练习。'
    }, {
        demo_link: 'http://gaohaoyang.github.io/ife/task/task0002/work/Gaohaoyang/index.html',
        img_link: 'http://7q5cdt.com1.z0.glb.clouddn.com/demo-demo-index.png',
        code_link: 'https://github.com/Gaohaoyang/ife/tree/master/task/task0002/work/Gaohaoyang',
        title: '百度前端学院 task0002 展示主页',
        core_tech: 'HTML CSS',
        description: '任务二的展示主页，里面包含五个小 demo。还有一篇相关的日志。'
    }, {
        demo_link: 'http://gaohaoyang.github.io/ife/task/task0001/work/Gaohaoyang/index.html',
        img_link: 'http://7q5cdt.com1.z0.glb.clouddn.com/Demo-blog-ife.jpg',
        code_link: 'https://github.com/Gaohaoyang/ife/tree/master/task/task0001/work/Gaohaoyang',
        title: '百度前端学院 task0001 个人博客',
        core_tech: 'HTML CSS',
        description: '完成百度前端学院的任务。深刻的理解了BFC、浮动、inline-block间距，多列布局等技术。还有一篇相关的日志。'
    }, {
        demo_link: 'http://gaohaoyang.github.io/ghost-button-css3/',
        img_link: 'http://7q5cdt.com1.z0.glb.clouddn.com/DemoGhost-Button.png',
        code_link: 'https://github.com/Gaohaoyang/ghost-button-css3',
        title: 'Ghost Button 幽灵按钮',
        core_tech: 'CSS3',
        description: '使用 CSS3 中的旋转、缩放、过渡、动画等效果，制作出很酷的按钮效果。'
    }, {
        demo_link: 'http://gaohaoyang.github.io/shadow-demo-css3',
        img_link: 'http://7q5cdt.com1.z0.glb.clouddn.com/Demoshadow.png',
        code_link: 'https://github.com/Gaohaoyang/shadow-demo-css3',
        title: 'CSS3 阴影特效',
        core_tech: 'CSS3',
        description: 'CSS3 中的阴影、旋转等效果，制作出曲边阴影和翘边阴影。'
    }, {
        demo_link: 'http://gaohaoyang.github.io/learning-AngularJS/2-3-bookstore-add-sth-by-myself/',
        img_link: 'http://7q5cdt.com1.z0.glb.clouddn.com/DemoAngularJS.png',
        code_link: 'https://github.com/Gaohaoyang/learning-AngularJS/tree/master/2-3-bookstore-add-sth-by-myself',
        title: 'AngularJS 结合动画效果',
        core_tech: 'AngularJS CSS3',
        description: '使用 AngularJS 中的 ngAnimate 加 CSS3里面的一些旋转效果，做出页面切换的效果。'
    }, {
        demo_link: 'http://gaohaoyang.github.io/learning-AngularJS/2-4-UiRouterPractice',
        img_link: 'http://ww2.sinaimg.cn/large/7011d6cfjw1f3b8zumfqij20q40nh76x.jpg',
        code_link: 'https://github.com/Gaohaoyang/learning-AngularJS/tree/master/2-4-UiRouterPractice',
        title: 'AngularJS UI-router 练习',
        core_tech: 'AngularJS UI-router',
        description: 'UI-router 作为 AngularJS 中路由的扩充，实现了多级路由的效果。使得前端界面跳转更加方便。'
    }, {
        demo_link: 'http://gaohaoyang.github.io/test/bootstrap-zhihu/',
        img_link: 'http://7q5cdt.com1.z0.glb.clouddn.com/teach-girlfriend-html-CopyZhihu.jpg',
        code_link: 'https://github.com/Gaohaoyang/test/tree/master/bootstrap-zhihu',
        title: '仿知乎页面',
        core_tech: 'HTML BootStrap',
        description: '使用BootStrap仿照知乎做了一个静态页面。'
    }];

    contentInit(demoContent) //内容初始化
    waitImgsLoad() //等待图片加载，并执行布局初始化
}());

/**
 * 内容初始化
 * @return {[type]} [description]
 */
function contentInit(content) {
    // var htmlArr = [];
    // for (var i = 0; i < content.length; i++) {
    //     htmlArr.push('
')
    //     htmlArr.push('')
    //     htmlArr.push('')
    //     htmlArr.push('')
    //     htmlArr.push('
')
    //     htmlArr.push(''+content[i].title+'')
    //     htmlArr.push('
')
    //     htmlArr.push('
主要技术：'+content[i].core_tech+'
')
    //     htmlArr.push('
'+content[i].description)
    //     htmlArr.push('源代码 ')
    //     htmlArr.push('
')
    //     htmlArr.push('
')
    // }
    // var htmlStr = htmlArr.join('')
    var htmlStr = ''
    for (var i = 0; i < content.length; i++) {
        htmlStr +=
            '
' +
            '   ' +
            '       ' +
            '   ' +
            '
' +
            '       ' + content[i].title + '' +
            '
' +
            '
主要技术：' + content[i].core_tech + '
' +
            '
' + content[i].description +
            '       源代码 ' +
            '
' +
            '
'
    }
    var grid = document.querySelector('.grid')
    grid.insertAdjacentHTML('afterbegin', htmlStr)
}

/**
 * 等待图片加载
 * @return {[type]} [description]
 */
function waitImgsLoad() {
    var imgs = document.querySelectorAll('.grid img')
    var totalImgs = imgs.length
    var count = 0
        //console.log(imgs)
    for (var i = 0; i < totalImgs; i++) {
        if (imgs[i].complete) {
            //console.log('complete');
            count++
        } else {
            imgs[i].onload = function() {
                // alert('onload')
                count++
                //console.log('onload' + count)
                if (count == totalImgs) {
                    //console.log('onload---bbbbbbbb')
                    initGrid()
                }
            }
        }
    }
    if (count == totalImgs) {
        //console.log('---bbbbbbbb')
        initGrid()
    }
}

/**
 * 初始化栅格布局
 * @return {[type]} [description]
 */
function initGrid() {
    var msnry = new Masonry('.grid', {
        // options
        itemSelector: '.grid-item',
        columnWidth: 250,
        isFitWidth: true,
        gutter: 20,
    })
}
<|endoftext|>


<commit_before>/* jshint asi:true */
//先等图片都加载完成
//再执行布局函数

/**
 * 执行主函数
 * @param  {[type]} function( [description]
 * @return {[type]}           [description]
 */
(function() {

  /**
     * 内容JSON
     */
  var demoContent = [
    {
      demo_link: '../Demo/navbar/navbar.html',
      img_link: '../img/demoImg/navbar/navbar.png',
      code_link: 'https://github.com/minchao920917/Dome/tree/master/navbar',
      title: '一个简单的常用企业网站导航栏',
      core_tech: 'bootstrap,navbar',
      description: '常用公司官网的导航栏，兼容手机端'
    }, {
      demo_link: '../Demo/myModal/index.html',
      img_link: '../img/demoImg/myModal/modal.jpg',
      code_link: 'https://github.com/minchao920917/Dome/tree/master/myModal',
      title: '一个简单的模态框',
      core_tech: 'js、css、html',
      description: '纯手写模态框'
    },
    {
      demo_link: '../Demo/loading/index.html',
      img_link: 'https://ooo.0o0.ooo/2017/05/26/5927a823b94b2.jpg',
      code_link: 'https://github.com/minchao920917/Dome/tree/master/loading',
      title: '十一个loading特效集合',
      core_tech: 'js、css、html',
      description: '纯手写的loading动画'
    },
      {
          demo_link: '../Demo/scorlly/index.html',
          img_link: 'https://ooo.0o0.ooo/2017/06/21/594a183bc9b0d.png',
          code_link: 'https://github.com/minchao920917/Dome/tree/master/scorlly',
          title: '一划一页',
          core_tech: 'js、css、html',
          description: '鼠标滚动事件，页面自动上下滚动一屏幕'
      },
      {
          demo_link: '../Demo/explode/index.html',
          img_link: 'https://ooo.0o0.ooo/2017/06/21/594a2803d660a.png',
          code_link: 'https://github.com/minchao920917/Dome/tree/master/explode',
          title: '基于jquery的点击爆炸事件',
          core_tech: 'js、css、html',
          description: '点击爆炸事件，可控制分块数量'
      },
          {
              demo_link: '../Demo/tabLabel/index.html',
                  img_link: 'https://ooo.0o0.ooo/2017/06/23/594cd3ef50634.png',
              code_link: 'https://github.com/minchao920917/Dome/tree/master/tabLabel',
              title: 'css和js的tabl分栏',
              core_tech: 'js、css、html',
              description: '可以tab分栏，并兼容手机端'
          },
          {
              demo_link: '../Demo/videorun/index.html',
                  img_link: 'https://ooo.0o0.ooo/2017/06/23/594cd48973b40.png',
              code_link: 'https://github.com/minchao920917/Dome/tree/master/videorun',
              title: '视频播放',
              core_tech: 'js、css、html',
              description: '视频播放，兼容手机端，数据源放7牛网上'
          },
          {
              demo_link: '../Demo/svgAnimate/index.html',
                  img_link: 'https://ooo.0o0.ooo/2017/06/23/594cd4ffee171.png',
              code_link: 'https://github.com/minchao920917/Dome/tree/master/svgAnimate',
              title: 'svg动画',
              core_tech: 'js、css、html',
              description: '由css控制svg中的元素的动画'
          },
          {
              demo_link: '../Demo/H5Web/index.html',
              img_link: 'https://i.loli.net/2018/01/15/5a5c48dfd09af.png',
              code_link: 'https://github.com/minchao920917/Dome/tree/master/H5Web',
              title: '《HTML5移动Web开发实战》',
              core_tech: 'js、css、html',
              description: 'HTML5与移动网站，介绍HTML5和移动网站的基本概念和学习'
          },
         {
             demo_link: '../Demo/vue/index.html',
             img_link: 'https://ooo.0o0.ooo/2017/06/30/5955f276ed1c6.png',
             code_link: 'https://github.com/minchao920917/Dome/tree/master/vue',
             title: 'vuejs例子Demo',
             core_tech: 'vuejs、css、html',
             description: 'vue公司培训的Demo'
         },
        {
          demo_link: '../Demo/form/index.html',
          img_link: 'https://i.loli.net/2017/08/15/5992620778455.png',
          code_link: 'https://github.com/minchao920917/Dome/tree/master/form',
          title: '动态表单',
          core_tech: 'bootstrap、css、html',
          description: '基于bootstrap的动态表单，可添加，可减少的可，兼容手机端'
         },
          {
              demo_link: '../Demo/oldHomePage/index.html',
              img_link: 'https://i.loli.net/2017/08/22/599bc0d9dfd1d.png',
              code_link: 'https://github.com/minchao920917/Dome/tree/master/oldHomePage',
              title: '个人主页(old老的样本)',
              core_tech: 'bootstrap、css、html',
              description: '个人主页，未改版之前的版本'
          },
          {
              demo_link: '../Demo/2048/demo.html',
              img_link: 'https://i.loli.net/2017/08/24/599e3a014d1ae.png',
              code_link: 'https://github.com/minchao920917/Dome/tree/master/2048',
              title: '2048小游戏',
              core_tech: 'JavaScript、css、html',
              description: '2048小游戏，兼容手机端'
          },
          {
              demo_link: 'https://github.com/minchao920917/FAST',
              img_link: 'https://i.loli.net/2017/09/07/59b0bc6b8265c.jpg',
              code_link: 'https://github.com/minchao920917/FAST',
              title: 'FAST系统',
              core_tech: '手机端app页面合集',
              description: '该系统是自己模仿手机app写的，包括新闻列表、日期、FAQ、会议管理、预定页面，设置，个人中心等模块过程，只是用于练习，方便将来能快速开发。'
          },
           {
               demo_link: '../Demo/fullcalendar/index.html',
               img_link: 'https://i.loli.net/2017/12/28/5a44b1de59f65.png',
               code_link: 'https://github.com/minchao920917/Dome/tree/master/fullcalendar',
               title: 'fullcalendar插件例子',
               core_tech: 'javscript、css、html',
               description: 'fullcalendar的插件调用，纯手写周选择器，确定调用js'
           },
          {
              demo_link: 'https://github.com/minchao920917/Dome/tree/master/test_mysql',
              img_link: 'https://i.loli.net/2018/01/17/5a5ea8018379e.png',
              code_link: 'https://github.com/minchao920917/Dome/tree/master/test_mysql',
              title: 'node+express+mysql增删改查',
              core_tech: 'node、express、mysql',
              description: '使用node+mysql初步封装测试增删改查数据库'
          },
          {
              demo_link: '../Demo/timesAxis/index.html',
              img_link: 'https://i.loli.net/2018/04/28/5ae3ca7131ee4.png',
              code_link: 'https://github.com/minchao920917/time-axis',
              title: '纯css手写时间轴',
              core_tech: 'css',
              description: '使用node+mysql初步封装测试增删改查数据库'
          },
          {
              demo_link: '../Demo/opp_v2/index.html',
              img_link: 'https://i.loli.net/2018/08/29/5b86297fd82f2.png',
              code_link: 'https://github.com/minchao920917/time-axis',
              title: '活动日历翻页倒计时',
              core_tech: 'css+js',
              description: '使用jquery插件'
          }
  ];

  contentInit(demoContent) //内容初始化
  waitImgsLoad() //等待图片加载，并执行布局初始化
}());

/**
 * 内容初始化
 * @return {[type]} [description]
 */
function contentInit(content) {

  var htmlStr = ''
  for (var i = 0; i < content.length; i++) {
    htmlStr += '
' + '   ' + '       ' + '   ' + '
' + '       ' + content[i].title + '' + '
' + '
主要技术：' + content[i].core_tech + '
' + '
' + content[i].description + '       源代码 ' + '
' + '
'
  }
  var grid = document.querySelector('.grid')
  grid.insertAdjacentHTML('afterbegin', htmlStr)
}

/**
 * 等待图片加载
 * @return {[type]} [description]
 */
function waitImgsLoad() {
  var imgs = document.querySelectorAll('.grid img')
  var totalImgs = imgs.length
  var count = 0
  //console.log(imgs)
  for (var i = 0; i < totalImgs; i++) {
    if (imgs[i].complete) {
      //console.log('complete');
      count++
    } else {
      imgs[i].onload = function() {
        // alert('onload')
        count++
        //console.log('onload' + count)
        if (count == totalImgs) {
          //console.log('onload---bbbbbbbb')
          initGrid()
        }
      }
    }
  }
  if (count == totalImgs) {
    //console.log('---bbbbbbbb')
    initGrid()
  }
}

/**
 * 初始化栅格布局
 * @return {[type]} [description]
 */
function initGrid() {
  var msnry = new Masonry('.grid', {
    // options
    itemSelector: '.grid-item',
    columnWidth: 250,
    isFitWidth: true,
    gutter: 20
  })
}
<commit_msg>demo源码地址修改<commit_after>/* jshint asi:true */
//先等图片都加载完成
//再执行布局函数

/**
 * 执行主函数
 * @param  {[type]} function( [description]
 * @return {[type]}           [description]
 */
(function() {

  /**
     * 内容JSON
     */
  var demoContent = [
    {
      demo_link: '../Demo/navbar/navbar.html',
      img_link: '../img/demoImg/navbar/navbar.png',
      code_link: 'https://github.com/minchao920917/Dome/tree/master/navbar',
      title: '一个简单的常用企业网站导航栏',
      core_tech: 'bootstrap,navbar',
      description: '常用公司官网的导航栏，兼容手机端'
    }, {
      demo_link: '../Demo/myModal/index.html',
      img_link: '../img/demoImg/myModal/modal.jpg',
      code_link: 'https://github.com/minchao920917/Dome/tree/master/myModal',
      title: '一个简单的模态框',
      core_tech: 'js、css、html',
      description: '纯手写模态框'
    },
    {
      demo_link: '../Demo/loading/index.html',
      img_link: 'https://ooo.0o0.ooo/2017/05/26/5927a823b94b2.jpg',
      code_link: 'https://github.com/minchao920917/Dome/tree/master/loading',
      title: '十一个loading特效集合',
      core_tech: 'js、css、html',
      description: '纯手写的loading动画'
    },
      {
          demo_link: '../Demo/scorlly/index.html',
          img_link: 'https://ooo.0o0.ooo/2017/06/21/594a183bc9b0d.png',
          code_link: 'https://github.com/minchao920917/Dome/tree/master/scorlly',
          title: '一划一页',
          core_tech: 'js、css、html',
          description: '鼠标滚动事件，页面自动上下滚动一屏幕'
      },
      {
          demo_link: '../Demo/explode/index.html',
          img_link: 'https://ooo.0o0.ooo/2017/06/21/594a2803d660a.png',
          code_link: 'https://github.com/minchao920917/Dome/tree/master/explode',
          title: '基于jquery的点击爆炸事件',
          core_tech: 'js、css、html',
          description: '点击爆炸事件，可控制分块数量'
      },
          {
              demo_link: '../Demo/tabLabel/index.html',
                  img_link: 'https://ooo.0o0.ooo/2017/06/23/594cd3ef50634.png',
              code_link: 'https://github.com/minchao920917/Dome/tree/master/tabLabel',
              title: 'css和js的tabl分栏',
              core_tech: 'js、css、html',
              description: '可以tab分栏，并兼容手机端'
          },
          {
              demo_link: '../Demo/videorun/index.html',
                  img_link: 'https://ooo.0o0.ooo/2017/06/23/594cd48973b40.png',
              code_link: 'https://github.com/minchao920917/Dome/tree/master/videorun',
              title: '视频播放',
              core_tech: 'js、css、html',
              description: '视频播放，兼容手机端，数据源放7牛网上'
          },
          {
              demo_link: '../Demo/svgAnimate/index.html',
                  img_link: 'https://ooo.0o0.ooo/2017/06/23/594cd4ffee171.png',
              code_link: 'https://github.com/minchao920917/Dome/tree/master/svgAnimate',
              title: 'svg动画',
              core_tech: 'js、css、html',
              description: '由css控制svg中的元素的动画'
          },
          {
              demo_link: '../Demo/H5Web/index.html',
              img_link: 'https://i.loli.net/2018/01/15/5a5c48dfd09af.png',
              code_link: 'https://github.com/minchao920917/Dome/tree/master/H5Web',
              title: '《HTML5移动Web开发实战》',
              core_tech: 'js、css、html',
              description: 'HTML5与移动网站，介绍HTML5和移动网站的基本概念和学习'
          },
         {
             demo_link: '../Demo/vue/index.html',
             img_link: 'https://ooo.0o0.ooo/2017/06/30/5955f276ed1c6.png',
             code_link: 'https://github.com/minchao920917/Dome/tree/master/vue',
             title: 'vuejs例子Demo',
             core_tech: 'vuejs、css、html',
             description: 'vue公司培训的Demo'
         },
        {
          demo_link: '../Demo/form/index.html',
          img_link: 'https://i.loli.net/2017/08/15/5992620778455.png',
          code_link: 'https://github.com/minchao920917/Dome/tree/master/form',
          title: '动态表单',
          core_tech: 'bootstrap、css、html',
          description: '基于bootstrap的动态表单，可添加，可减少的可，兼容手机端'
         },
          {
              demo_link: '../Demo/oldHomePage/index.html',
              img_link: 'https://i.loli.net/2017/08/22/599bc0d9dfd1d.png',
              code_link: 'https://github.com/minchao920917/Dome/tree/master/oldHomePage',
              title: '个人主页(old老的样本)',
              core_tech: 'bootstrap、css、html',
              description: '个人主页，未改版之前的版本'
          },
          {
              demo_link: '../Demo/2048/demo.html',
              img_link: 'https://i.loli.net/2017/08/24/599e3a014d1ae.png',
              code_link: 'https://github.com/minchao920917/Dome/tree/master/2048',
              title: '2048小游戏',
              core_tech: 'JavaScript、css、html',
              description: '2048小游戏，兼容手机端'
          },
          {
              demo_link: 'https://github.com/minchao920917/FAST',
              img_link: 'https://i.loli.net/2017/09/07/59b0bc6b8265c.jpg',
              code_link: 'https://github.com/minchao920917/FAST',
              title: 'FAST系统',
              core_tech: '手机端app页面合集',
              description: '该系统是自己模仿手机app写的，包括新闻列表、日期、FAQ、会议管理、预定页面，设置，个人中心等模块过程，只是用于练习，方便将来能快速开发。'
          },
           {
               demo_link: '../Demo/fullcalendar/index.html',
               img_link: 'https://i.loli.net/2017/12/28/5a44b1de59f65.png',
               code_link: 'https://github.com/minchao920917/Dome/tree/master/fullcalendar',
               title: 'fullcalendar插件例子',
               core_tech: 'javscript、css、html',
               description: 'fullcalendar的插件调用，纯手写周选择器，确定调用js'
           },
          {
              demo_link: 'https://github.com/minchao920917/Dome/tree/master/test_mysql',
              img_link: 'https://i.loli.net/2018/01/17/5a5ea8018379e.png',
              code_link: 'https://github.com/minchao920917/Dome/tree/master/test_mysql',
              title: 'node+express+mysql增删改查',
              core_tech: 'node、express、mysql',
              description: '使用node+mysql初步封装测试增删改查数据库'
          },
          {
              demo_link: '../Demo/timesAxis/index.html',
              img_link: 'https://i.loli.net/2018/04/28/5ae3ca7131ee4.png',
              code_link: 'https://github.com/minchao920917/time-axis',
              title: '纯css手写时间轴',
              core_tech: 'css',
              description: '使用node+mysql初步封装测试增删改查数据库'
          },
          {
              demo_link: '../Demo/opp_v2/index.html',
              img_link: 'https://i.loli.net/2018/08/29/5b86297fd82f2.png',
              code_link: 'https://github.com/minchao920917/Dome/tree/master/opp_v2',
              title: '活动日历翻页倒计时',
              core_tech: 'css+js',
              description: '使用jquery插件'
          }
  ];

  contentInit(demoContent) //内容初始化
  waitImgsLoad() //等待图片加载，并执行布局初始化
}());

/**
 * 内容初始化
 * @return {[type]} [description]
 */
function contentInit(content) {

  var htmlStr = ''
  for (var i = 0; i < content.length; i++) {
    htmlStr += '
' + '   ' + '       ' + '   ' + '
' + '       ' + content[i].title + '' + '
' + '
主要技术：' + content[i].core_tech + '
' + '
' + content[i].description + '       源代码 ' + '
' + '
'
  }
  var grid = document.querySelector('.grid')
  grid.insertAdjacentHTML('afterbegin', htmlStr)
}

/**
 * 等待图片加载
 * @return {[type]} [description]
 */
function waitImgsLoad() {
  var imgs = document.querySelectorAll('.grid img')
  var totalImgs = imgs.length
  var count = 0
  //console.log(imgs)
  for (var i = 0; i < totalImgs; i++) {
    if (imgs[i].complete) {
      //console.log('complete');
      count++
    } else {
      imgs[i].onload = function() {
        // alert('onload')
        count++
        //console.log('onload' + count)
        if (count == totalImgs) {
          //console.log('onload---bbbbbbbb')
          initGrid()
        }
      }
    }
  }
  if (count == totalImgs) {
    //console.log('---bbbbbbbb')
    initGrid()
  }
}

/**
 * 初始化栅格布局
 * @return {[type]} [description]
 */
function initGrid() {
  var msnry = new Masonry('.grid', {
    // options
    itemSelector: '.grid-item',
    columnWidth: 250,
    isFitWidth: true,
    gutter: 20
  })
}
<|endoftext|>


<commit_before>define(['config/config'],function(cfg){

	var connection = function(url, modelElement){
		this.url = url;
		this.modelElement = modelElement;

		this.connect();
	};

	connection.prototype.connect = function(){
		var thi$ = this;
		this.ws = new WebSocket(this.url);
		this.ws.onmessage= function(data) {
			var json = JSON.parse(data.data);
			if(json.modelBinding && json.modelValue){
				var a = thi$.modelElement.getElementsByAttr(cfg.prefix + "-model-binding="+json.modelBinding);
				for(var i in a){
					var elm = a[i];
					elm.val(json.modelValue);
				}
			} else {
				for(var k in json){
					var a = thi$.modelElement.getElementsByAttr(cfg.prefix + "-model-binding="+k);
					for(var i in a){
						var elm = a[i];
						elm.val(json[k]);
					}
				}
			}
		};
	};

	return connection;
});<commit_msg>added send to our websocket object wrapper<commit_after>define(['config/config'],function(cfg){

	var connection = function(url, modelElement){
		this.url = url;
		this.modelElement = modelElement;

		this.connect();
	};

	connection.prototype.connect = function(){
		var thi$ = this;
		this.ws = new WebSocket(this.url);
		this.ws.onmessage= function(data) {
			var json = JSON.parse(data.data);
			if(json.modelBinding && json.modelValue){
				var a = thi$.modelElement.getElementsByAttr(cfg.prefix + "-model-binding="+json.modelBinding);
				for(var i in a){
					var elm = a[i];
					elm.val(json.modelValue);
				}
			} else {
				for(var k in json){
					var a = thi$.modelElement.getElementsByAttr(cfg.prefix + "-model-binding="+k);
					for(var i in a){
						var elm = a[i];
						elm.val(json[k]);
					}
				}
			}
		};
	};

	connection.prototype.send = function(obj){
		this.ws.send(obj);
	};

	return connection;
});<|endoftext|>