<commit_before>###*
# @overview Defines the `HasValidators` trait which adds validation
# messages to a component.
#
# @module stout-ui/input/HasValidators
###
debounce   = require 'lodash/debounce'
Foundation = require 'stout-core/base/Foundation'
parser     = require '../validator/parser'


VALIDATION_DEBOUNCE = 300

###*
# The `HasValidatorsView`
#
# @exports stout-ui/traits/HasValidatorsView
# @mixin
###
module.exports = class HasValidatorsView extends Foundation

  ###*
  # The `validators` attribut on views which include this trait. `Validator`
  # classes are automatically instantiated based on this property.
  #
  # @member validators
  # @memberof stout-ui/traits/HasValidatorsView#
  ###
  @property 'validators',
    default: ''


  ###*
  # Optional field name for use by validators.
  #
  # @member validatorName
  # @memberof stout-ui/traits/HasValidatorsView#
  ###
  @property 'validatorName'


  ###*
  # Set to `true` to enabled the "required" validator for this field.
  #
  # @member required
  # @memberof stout-ui/traits/HasValidatorsView#
  ###
  @property 'required',
    default: false
    type: 'boolean'


  ###*
  # Initiates this trait.
  #
  # @method initTrait
  # @memberof stout-ui/traits/HasValidatorsView#
  # @private
  ###
  initTrait: ->
    # Add the "required" validator if the attribute has been set.
    if @required then @validators += '|required'

    # Parse the described validators.
    if @validators.trim().length > 0
      for v in parser.parse(@validators)
        v.name = @validatorName or @label
        @context.validators.add v

    # Handles actually performing the full validation using the view-model's
    # validator group.
    doValidation = =>
      if @visited
        @context.validatorGroup.validate @context[@context.validateProperty]

    # This function handles debounced, live validation.
    doLiveValidation = debounce ->
      doValidation()
    , VALIDATION_DEBOUNCE

    # Perform a full validation when the field is blurred.
    @on 'blur', => if @dirty then doValidation()

    @on 'focus', =>
      val = @context[@context.validateProperty]
      @context.validatorGroup.softValidate(val)

    # When the field changes, perform a live debounced full validation.
    @context.on "change:#{@context.validateProperty}", doLiveValidation
<commit_msg>Update how and when validations are triggered.<commit_after>###*
# @overview Defines the `HasValidators` trait which adds validation
# messages to a component.
#
# @module stout-ui/input/HasValidators
###
debounce   = require 'lodash/debounce'
Foundation = require 'stout-core/base/Foundation'
parser     = require '../validator/parser'


###*
# Inner constant used for debouncing validation related functions.
#
# @const number
# @inner
###
VALIDATION_DEBOUNCE = 100



###*
# The `HasValidatorsView`
#
# @exports stout-ui/traits/HasValidatorsView
# @mixin
###
module.exports = class HasValidatorsView extends Foundation

  ###*
  # The `validators` attribut on views which include this trait. `Validator`
  # classes are automatically instantiated based on this property.
  #
  # @member validators
  # @memberof stout-ui/traits/HasValidatorsView#
  ###
  @property 'validators',
    default: ''


  ###*
  # Optional field name for use by validators.
  #
  # @member validatorName
  # @memberof stout-ui/traits/HasValidatorsView#
  ###
  @property 'validatorName'


  ###*
  # Set to `true` to enabled the "required" validator for this field.
  #
  # @member required
  # @memberof stout-ui/traits/HasValidatorsView#
  ###
  @property 'required',
    default: false
    type: 'boolean'


  ###*
  # Initiates this trait.
  #
  # @method initTrait
  # @memberof stout-ui/traits/HasValidatorsView#
  # @private
  ###
  initTrait: ->
    # Add the "required" validator if the attribute has been set.
    if @required then @validators += '|required'

    # Parse the described validators.
    if @validators.trim().length > 0
      for v in parser.parse(@validators)
        v.name = @validatorName or @label
        @context.validators.add v

    # Handles actually performing the full validation using the view-model's
    # validator group.
    doValidation = =>
      if @visited
        @context.validatorGroup.validate @context[@context.validateProperty]

    # This function handles debounced, live validation.
    doLiveValidation = debounce ->
      doValidation()
    , VALIDATION_DEBOUNCE

    # Perform a full validation when the field is blurred. We have to debounce
    # this listener most importantly because we depend on the `#dirty` property
    # being set correctly on the first blur event. This happens syncronously
    # but this method may be called before `#dirty` is set. Therefore, we
    # debounce to ensure the event loop has cleared and the property is set
    # correctly.
    @on 'blur', debounce =>
      if @dirty then doValidation()
    , VALIDATION_DEBOUNCE

    @on 'focus', =>
      @context.validatorGroup.softValidate  @context[@context.validateProperty]

    # When the field changes, perform a live debounced full validation.
    @context.on "change:#{@context.validateProperty}", (e) =>
      @context.validatorGroup.softValidate(e.data.value)

    # When a view "bump" occurs, also perform a validation.
    @on 'bump:maxlength', (e) =>
      @context.validatorGroup.softValidate(e.data)

{'fraction_non_alphanumeric': 0.10908073839269065, 'fraction_numerical': 0.0014917024053701287, 'mean_word_length': 3.4625623960066556, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4608260', 'n_tokens_mistral': 1632, 'n_tokens_neox': 1566, 'n_words': 474}