text: (function (root, factory) {
    if (typeof define === 'function' && define.amd) {
      // AMD. Register as an anonymous module unless amdModuleId is set
      define(["jquery"], function (a0) {
        return (factory(a0));
      });
    } else if (typeof exports === 'object') {
      // Node. Does not work with strict CommonJS, but
      // only CommonJS-like environments that support module.exports,
      // like Node.
      module.exports = factory(require("jquery"));
    } else {
      factory(jQuery);
    }
  }(this, function (jQuery) {
  
  /** File generated by Grunt -- do not modify
   *  JQUERY-FORM-VALIDATOR
   *
   *  @version 2.3.26
   *  @website http://formvalidator.net/
   *  @author Victor Jonsson, http://victorjonsson.se
   *  @license MIT
   */
  /**
   * Deprecated functions and attributes
   * @todo: Remove in release of 3.0
   */
  (function ($, undefined) {
  
    'use strict';
  
    /**
     * @deprecated
     * @param language
     * @param conf
     */
    $.fn.validateForm = function (language, conf) {
      $.formUtils.warn('Use of deprecated function $.validateForm, use $.isValid instead');
      return this.isValid(language, conf, true);
    };
  
    $(window).on('validatorsLoaded formValidationSetup', function(evt, $form, config) {
      if( !$form ) {
        $form = $('form');
      }
  
      addSupportForCustomErrorMessageCallback(config);
      addSupportForElementReferenceInPositionParam(config);
      addSupportForValidationDependingOnCheckedInput($form);
    });
  
  
    function addSupportForCustomErrorMessageCallback(config) {
      if (config &&
          config.errorMessagePosition === 'custom' &&
          typeof config.errorMessageCustom === 'function') {
  
        $.formUtils.warn('Use of deprecated function errorMessageCustom, use config.submitErrorMessageCallback instead');
  
        config.submitErrorMessageCallback = function($form, errorMessages) {
          config.errorMessageCustom(
              $form,
              config.language.errorTitle,
              errorMessages,
              config
          );
        };
      }
    }
  
    function addSupportForElementReferenceInPositionParam(config) {
      if (config.errorMessagePosition && typeof config.errorMessagePosition === 'object') {
        $.formUtils.warn('Deprecated use of config parameter errorMessagePosition, use config.submitErrorMessageCallback instead');
        var $errorMessageContainer = config.errorMessagePosition;
        config.errorMessagePosition = 'top';
        config.submitErrorMessageCallback = function() {
          return $errorMessageContainer;
        };
      }
    }
  
    function addSupportForValidationDependingOnCheckedInput($form) {
      var $inputsDependingOnCheckedInputs = $form.find('[data-validation-if-checked]');
      if ($inputsDependingOnCheckedInputs.length) {
        $.formUtils.warn(
          'Detected use of attribute "data-validation-if-checked" which is '+
          'deprecated. Use "data-validation-depends-on" provided by module "logic"'
        );
      }
  
      $inputsDependingOnCheckedInputs
        .on('beforeValidation', function() {
  
          var $elem = $(this),
            nameOfDependingInput = $elem.valAttr('if-checked');
  
          // Set the boolean telling us that the validation depends
          // on another input being checked
          var $dependingInput = $('input[name="' + nameOfDependingInput + '"]', $form),
            dependingInputIsChecked = $dependingInput.is(':checked'),
            valueOfDependingInput = ($.formUtils.getValue($dependingInput) || '').toString(),
            requiredValueOfDependingInput = $elem.valAttr('if-checked-value');
  
          if (!dependingInputIsChecked || !(
                !requiredValueOfDependingInput ||
                requiredValueOfDependingInput === valueOfDependingInput
            )) {
            $elem.valAttr('skipped', true);
          }
  
        });
      }
  
  })(jQuery);
  
  /**
   * Utility methods used for displaying error messages (attached to $.formUtils)
   */
  (function ($) {
  
    'use strict';
  
    var dialogs = {
  
      resolveErrorMessage: function($elem, validator, validatorName, conf, language) {
        var errorMsgAttr = conf.validationErrorMsgAttribute + '-' + validatorName.replace('validate_', ''),
          validationErrorMsg = $elem.attr(errorMsgAttr);
  
        if (!validationErrorMsg) {
          validationErrorMsg = $elem.attr(conf.validationErrorMsgAttribute);
          if (!validationErrorMsg) {
            if (typeof validator.errorMessageKey !== 'function') {
              validationErrorMsg = language[validator.errorMessageKey];
            }
            else {
              validationErrorMsg = language[validator.errorMessageKey(conf)];
            }
            if (!validationErrorMsg) {
              validationErrorMsg = validator.errorMessage;
            }
          }
        }
        return validationErrorMsg;
      },
      getParentContainer: function ($elem) {
        if ($elem.valAttr('error-msg-container')) {
          return $($elem.valAttr('error-msg-container'));
        } else {
          var $parent = $elem.parent();
          if (!$parent.hasClass('form-group') && !$parent.closest('form').hasClass('form-horizontal')) {
            var $formGroup = $parent.closest('.form-group');
            if ($formGroup.length) {
              return $formGroup.eq(0);
            }
          }
          return $parent;
        }
      },
      applyInputErrorStyling: function ($input, conf) {
        $input
          .addClass(conf.errorElementClass)
          .removeClass('valid');
  
        this.getParentContainer($input)
          .addClass(conf.inputParentClassOnError)
          .removeClass(conf.inputParentClassOnSuccess);
  
        if (conf.borderColorOnError !== '') {
          $input.css('border-color', conf.borderColorOnError);
        }
      },
      applyInputSuccessStyling: function($input, conf) {
        $input.addClass('valid');
        this.getParentContainer($input)
          .addClass(conf.inputParentClassOnSuccess);
      },
      removeInputStylingAndMessage: function($input, conf) {
  
        // Reset input css
        $input
          .removeClass('valid')
          .removeClass(conf.errorElementClass)
          .css('border-color', '');
  
        var $parentContainer = dialogs.getParentContainer($input);
  
        // Reset parent css
        $parentContainer
          .removeClass(conf.inputParentClassOnError)
          .removeClass(conf.inputParentClassOnSuccess);
  
        // Remove possible error message
        if (typeof conf.inlineErrorMessageCallback === 'function') {
          var $errorMessage = conf.inlineErrorMessageCallback($input, false, conf);
          if ($errorMessage) {
            $errorMessage.html('');
          }
        } else {
          $parentContainer
            .find('.' + conf.errorMessageClass)
            .remove();
        }
  
      },
      removeAllMessagesAndStyling: function($form, conf) {
  
        // Remove error messages in top of form
        if (typeof conf.submitErrorMessageCallback === 'function') {
          var $errorMessagesInTopOfForm = conf.submitErrorMessageCallback($form, conf);
          if ($errorMessagesInTopOfForm) {
            $errorMessagesInTopOfForm.html('');
          }
        } else {
          $form.find('.' + conf.errorMessageClass + '.alert').remove();
        }
  
        // Remove input css/messages
        $form.find('.' + conf.errorElementClass + ',.valid').each(function() {
          dialogs.removeInputStylingAndMessage($(this), conf);
        });
      },
      setInlineMessage: function ($input, errorMsg, conf) {
  
        this.applyInputErrorStyling($input, conf);
  
        var custom = document.getElementById($input.attr('name') + '_err_msg'),
          $messageContainer = false,
          setErrorMessage = function ($elem) {
            $.formUtils.$win.trigger('validationErrorDisplay', [$input, $elem]);
            $elem.html(errorMsg);
          },
          addErrorToMessageContainer = function() {
            var $found = false;
            $messageContainer.find('.' + conf.errorMessageClass).each(function () {
              if (this.inputReferer === $input[0]) {
                $found = $(this);
                return false;
              }
            });
            if ($found) {
              if (!errorMsg) {
                $found.remove();
              } else {
                setErrorMessage($found);
              }
            } else if(errorMsg !== '') {
              $message = $('<div class="' + conf.errorMessageClass + ' alert"></div>');
              setErrorMessage($message);
              $message[0].inputReferer = $input[0];
              $messageContainer.prepend($message);
            }
          },
          $message;
  
        if (custom) {
          // Todo: remove in 3.0
          $.formUtils.warn('Using deprecated element reference ' + custom.id);
          $messageContainer = $(custom);
          addErrorToMessageContainer();
        } else if (typeof conf.inlineErrorMessageCallback === 'function') {
          $messageContainer = conf.inlineErrorMessageCallback($input, errorMsg, conf);
          if (!$messageContainer) {
            // Error display taken care of by inlineErrorMessageCallback
            return;
          }
          addErrorToMessageContainer();
        } else {
          var $parent = this.getParentContainer($input);
          $message = $parent.find('.' + conf.errorMessageClass + '.help-block');
          if ($message.length === 0) {
            $message = $('<span></span>').addClass('help-block').addClass(conf.errorMessageClass);
            $message.appendTo($parent);
          }
          setErrorMessage($message);
        }
      },
      setMessageInTopOfForm: function ($form, errorMessages, conf, lang) {
        var view = '<div class="{errorMessageClass} alert alert-danger">'+
                      '<strong>{errorTitle}</strong>'+
                      '<ul>{fields}</ul>'+
                  '</div>',
            $container = false;
  
        if (typeof conf.submitErrorMessageCallback === 'function') {
          $container = conf.submitErrorMessageCallback($form, errorMessages, conf);
          if (!$container) {
            // message display taken care of by callback
            return;
          }
        }
  
        var viewParams = {
              errorTitle: lang.errorTitle,
              fields: '',
              errorMessageClass: conf.errorMessageClass
            };
  
        $.each(errorMessages, function (i, msg) {
          viewParams.fields += '<li>'+msg+'</li>';
        });
  
        $.each(viewParams, function(param, value) {
          view = view.replace('{'+param+'}', value);
        });
  
        if ($container) {
          $container.html(view);
        } else {
          $form.children().eq(0).before($(view));
        }
      }
    };
  
    $.formUtils = $.extend($.formUtils || {}, {
      dialogs: dialogs
    });
  
  })(jQuery);
  
  /**
   * File declaring all methods if this plugin which is applied to $.fn.
   */
  (function($, window, undefined) {
  
    'use strict';
  
    var _helpers = 0;
  
  
    /**
     * Assigns validateInputOnBlur function to elements blur event
     *
     * @param {Object} language Optional, will override $.formUtils.LANG
     * @param {Object} conf Optional, will override the default settings
     * @return {jQuery}
     */
    $.fn.validateOnBlur = function (language, conf) {
      var $form = this,
          $elems = this.find('*[data-validation]');
  
      $elems.each(function(){
        var $this = $(this);
        if ($this.is('[type=radio]')){
          var $additionals = $form.find('[type=radio][name="' + $this.attr('name') + '"]');
          $additionals.bind('blur.validation', function(){
            $this.validateInputOnBlur(language, conf, true, 'blur');
          });
          if (conf.validateCheckboxRadioOnClick) {
            $additionals.bind('click.validation', function () {
              $this.validateInputOnBlur(language, conf, true, 'click');
            });
          }
        }
      });
  
      $elems.bind('blur.validation', function () {
        $(this).validateInputOnBlur(language, conf, true, 'blur');
      });
  
      if (conf.validateCheckboxRadioOnClick) {
        // bind click event to validate on click for radio & checkboxes for nice UX
        this.find('input[type=checkbox][data-validation],input[type=radio][data-validation]')
          .bind('click.validation', function () {
            $(this).validateInputOnBlur(language, conf, true, 'click');
          });
      }
  
      return this;
    };
  
    /*
     * Assigns validateInputOnBlur function to elements custom event
     * @param {Object} language Optional, will override $.formUtils.LANG
     * @param {Object} settings Optional, will override the default settings
     * * @return {jQuery}
     */
    $.fn.validateOnEvent = function (language, config) {
      var $elements = this[0].nodeName === 'FORM' ? this.find('*[data-validation-event]') : this;
      $elements
        .each(function () {
          var $el = $(this),
            etype = $el.valAttr('event');
          if (etype) {
            $el
              .unbind(etype + '.validation')
              .bind(etype + '.validation', function (evt) {
                if( (evt || {}).keyCode !== 9 ) {
                  $(this).validateInputOnBlur(language, config, true, etype);
                }
              });
          }
        });
      return this;
    };
  
    /**
     * fade in help message when input gains focus
     * fade out when input loses focus
     * <input data-help="The info that I want to display for the user when input is focused" ... />
     *
     * @param {String} attrName - Optional, default is data-help
     * @return {jQuery}
     */
    $.fn.showHelpOnFocus = function (attrName) {
      if (!attrName) {
        attrName = 'data-validation-help';
      }
  
      // Remove previously added event listeners
      this.find('.has-help-txt')
        .valAttr('has-keyup-event', false)
        .removeClass('has-help-txt');
  
      // Add help text listeners
      this.find('textarea,input').each(function () {
        var $elem = $(this),
          className = 'jquery_form_help_' + (++_helpers),
          help = $elem.attr(attrName);
  
        if (help) {
          $elem
            .addClass('has-help-txt')
            .unbind('focus.help')
            .bind('focus.help', function () {
              var $help = $elem.parent().find('.' + className);
              if ($help.length === 0) {
                $help = $('<span />')
                  .addClass(className)
                  .addClass('help')
                  .addClass('help-block') // twitter bs
                  .text(help)
                  .hide();
  
                $elem.after($help);
              }
              $help.fadeIn();
            })
            .unbind('blur.help')
            .bind('blur.help', function () {
              $(this)
                .parent()
                .find('.' + className)
                .fadeOut('slow');
            });
        }
      });
  
      return this;
    };
  
    /**
     * @param {Function} cb
     * @param {Object} [conf]
     * @param {Object} [lang]
     */
    $.fn.validate = function(cb, conf, lang) {
      var language = $.extend({}, $.formUtils.LANG, lang || {});
      this.each(function() {
        var $elem = $(this),
          formDefaultConfig = $elem.closest('form').get(0).validationConfig || {};
  
        $elem.one('validation', function(evt, isValid) {
          if ( typeof cb === 'function' ) {
            cb(isValid, this, evt);
          }
        });
  
        $elem.validateInputOnBlur(
          language,
          $.extend({}, formDefaultConfig, conf || {}),
          true
        );
      });
    };
  
    /**
     * Tells whether or not validation of this input will have to postpone the form submit ()
     * @returns {Boolean}
     */
    $.fn.willPostponeValidation = function() {
      return (this.valAttr('suggestion-nr') ||
        this.valAttr('postpone') ||
        this.hasClass('hasDatepicker')) &&
        !window.postponedValidation;
    };
  
    /**
     * Validate single input when it loses focus
     * shows error message in a span element
     * that is appended to the parent element
     *
     * @param {Object} [language] Optional, will override $.formUtils.LANG
     * @param {Object} [conf] Optional, will override the default settings
     * @param {Boolean} attachKeyupEvent Optional
     * @param {String} eventType
     * @return {jQuery}
     */
    $.fn.validateInputOnBlur = function (language, conf, attachKeyupEvent, eventType) {
  
      $.formUtils.eventType = eventType;
  
      if ( this.willPostponeValidation() ) {
        // This validation has to be postponed
        var _self = this,
          postponeTime = this.valAttr('postpone') || 200;
  
        window.postponedValidation = function () {
          _self.validateInputOnBlur(language, conf, attachKeyupEvent, eventType);
          window.postponedValidation = false;
        };
  
        setTimeout(function () {
          if (window.postponedValidation) {
            window.postponedValidation();
          }
        }, postponeTime);
  
        return this;
      }
  
      language = $.extend({}, $.formUtils.LANG, language || {});
      $.formUtils.dialogs.removeInputStylingAndMessage(this, conf);
  
      var $elem = this,
        $form = $elem.closest('form'),
        result = $.formUtils.validateInput(
          $elem,
          language,
          conf,
          $form,
          eventType
        );
  
      if (attachKeyupEvent) {
        $elem.unbind('keyup.validation');
      }
  
      if (result.shouldChangeDisplay) {
        if (result.isValid) {
          $.formUtils.dialogs.applyInputSuccessStyling($elem, conf);
        } else {
          $.formUtils.dialogs.setInlineMessage($elem, result.errorMsg, conf);
        }
      }
  
      if (!result.isValid && attachKeyupEvent) {
        $elem.bind('keyup.validation', function (evt) {
          if( evt.keyCode !== 9 ) {
            $(this).validateInputOnBlur(language, conf, false, 'keyup');
          }
        });
      }
  
      return this;
    };
  
    /**
     * Short hand for fetching/adding/removing element attributes
     * prefixed with 'data-validation-'
     *
     * @param {String} name
     * @param {String|Boolean} [val]
     * @return {String|undefined|jQuery}
     * @protected
     */
    $.fn.valAttr = function (name, val) {
      if (val === undefined) {
        return this.attr('data-validation-' + name);
      } else if (val === false || val === null) {
        return this.removeAttr('data-validation-' + name);
      } else {
        name = ((name.length > 0) ? '-' + name : '');
        return this.attr('data-validation' + name, val);
      }
    };
  
    /**
     * Function that validates all inputs in active form
     *
     * @param {Object} [language]
     * @param {Object} [conf]
     * @param {Boolean} [displayError] Defaults to true
     */
    $.fn.isValid = function (language, conf, displayError) {
  
      if ($.formUtils.isLoadingModules) {
        var $self = this;
        setTimeout(function () {
          $self.isValid(language, conf, displayError);
        }, 200);
        return null;
      }
  
      conf = $.extend({}, $.formUtils.defaultConfig(), conf || {});
      language = $.extend({}, $.formUtils.LANG, language || {});
      displayError = displayError !== false;
  
      if ($.formUtils.errorDisplayPreventedWhenHalted) {
        // isValid() was called programmatically with argument displayError set
        // to false when the validation was halted by any of the validators
        delete $.formUtils.errorDisplayPreventedWhenHalted;
        displayError = false;
      }
  
      $.formUtils.isValidatingEntireForm = true;
      $.formUtils.haltValidation = false;
  
      /**
       * Adds message to error message stack if not already in the message stack
       *
       * @param {String} mess
       * @para {jQuery} $elem
       */
      var addErrorMessage = function (mess, $elem) {
          if ($.inArray(mess, errorMessages) < 0) {
            errorMessages.push(mess);
          }
          errorInputs.push($elem);
          $elem.attr('current-error', mess);
          if (displayError) {
            $.formUtils.dialogs.applyInputErrorStyling($elem, conf);
          }
        },
  
        /** Holds inputs (of type checkox or radio) already validated, to prevent recheck of mulitple checkboxes & radios */
        checkedInputs = [],
  
        /** Error messages for this validation */
        errorMessages = [],
  
        /** Input elements which value was not valid */
        errorInputs = [],
  
        /** Form instance */
        $form = this,
  
        /**
         * Tells whether or not to validate element with this name and of this type
         *
         * @param {String} name
         * @param {String} type
         * @return {Boolean}
         */
        ignoreInput = function (name, type) {
          if (type === 'submit' || type === 'button' || type === 'reset') {
            return true;
          }
          return $.inArray(name, conf.ignore || []) > -1;
        };
  
      // Reset style and remove error class
      if (displayError) {
        $.formUtils.dialogs.removeAllMessagesAndStyling($form, conf);
      }
  
      // Validate element values
      $form.find('input,textarea,select').filter(':not([type="submit"],[type="button"])').each(function () {
        var $elem = $(this),
          elementType = $elem.attr('type'),
          isCheckboxOrRadioBtn = elementType === 'radio' || elementType === 'checkbox',
          elementName = $elem.attr('name');
  
        if (!ignoreInput(elementName, elementType) && (!isCheckboxOrRadioBtn || $.inArray(elementName, checkedInputs) < 0)) {
  
          if (isCheckboxOrRadioBtn) {
            checkedInputs.push(elementName);
          }
  
          var result = $.formUtils.validateInput(
            $elem,
            language,
            conf,
            $form,
            'submit'
          );
  
          if (!result.isValid) {
            addErrorMessage(result.errorMsg, $elem);
          } else if (result.isValid && result.shouldChangeDisplay) {
            $elem.valAttr('current-error', false);
            $.formUtils.dialogs.applyInputSuccessStyling($elem, conf);
          }
        }
  
      });
  
      // Run validation callback
      if (typeof conf.onValidate === 'function') {
        var errors = conf.onValidate($form);
        if ($.isArray(errors)) {
          $.each(errors, function (i, err) {
            addErrorMessage(err.message, err.element);
          });
        }
        else if (errors && errors.element && errors.message) {
          addErrorMessage(errors.message, errors.element);
        }
      }
  
      // Reset form validation flag
      $.formUtils.isValidatingEntireForm = false;
  
      // Validation failed
      if (!$.formUtils.haltValidation && errorInputs.length > 0) {
  
        if (displayError) {
  
          if (conf.errorMessagePosition === 'top') {
            $.formUtils.dialogs.setMessageInTopOfForm($form, errorMessages, conf, language);
          } else {
            $.each(errorInputs, function (i, $input) {
              $.formUtils.dialogs.setInlineMessage($input, $input.attr('current-error'), conf);
            });
          }
          if (conf.scrollToTopOnError) {
            $.formUtils.$win.scrollTop($form.offset().top - 20);
          }
  
        }
  
        return false;
      }
  
      if (!displayError && $.formUtils.haltValidation) {
        $.formUtils.errorDisplayPreventedWhenHalted = true;
      }
  
      return !$.formUtils.haltValidation;
    };
  
    /**
     * Plugin for displaying input length restriction
     */
    $.fn.restrictLength = function (maxLengthElement) {
      new $.formUtils.lengthRestriction(this, maxLengthElement);
      return this;
    };
  
    /**
     * Add suggestion dropdown to inputs having data-suggestions with a comma
     * separated string with suggestions
     * @param {Array} [settings]
     * @returns {jQuery}
     */
    $.fn.addSuggestions = function (settings) {
      var sugs = false;
      this.find('input').each(function () {
        var $field = $(this);
  
        sugs = $.split($field.attr('data-suggestions'));
  
        if (sugs.length > 0 && !$field.hasClass('has-suggestions')) {
          $.formUtils.suggest($field, sugs, settings);
          $field.addClass('has-suggestions');
        }
      });
      return this;
    };
  
  
  })(jQuery, window);
  
  /**
   * Utility methods used for handling loading of modules (attached to $.formUtils)
   */
  (function($) {
  
    'use strict';
  
    $.formUtils = $.extend($.formUtils || {}, {
  
      /**
       * @var {Boolean}
       */
      isLoadingModules: false,
  
      /**
       * @var {Object}
       */
      loadedModules: {},
  
      /**
       * @example
       *  $.formUtils.loadModules('date, security.dev');
       *
       * Will load the scripts date.js and security.dev.js from the
       * directory where this script resides. If you want to load
       * the modules from another directory you can use the
       * path argument.
       *
       * The script will be cached by the browser unless the module
       * name ends with .dev
       *
       * @param {String} modules - Comma separated string with module file names (no directory nor file extension)
       * @param {String} [path] - Optional, path where the module files is located if their not in the same directory as the core modules
       * @param {function} [callback] - Optional, whether or not to fire event 'load' when modules finished loading
       */
      loadModules: function (modules, path, callback) {
  
        if ($.formUtils.isLoadingModules) {
          setTimeout(function () {
            $.formUtils.loadModules(modules, path, callback);
          }, 10);
          return;
        }
  
        var hasLoadedAnyModule = false,
          loadModuleScripts = function (modules, path) {
  
            var moduleList = $.split(modules),
              numModules = moduleList.length,
              moduleLoadedCallback = function () {
                numModules--;
                if (numModules === 0) {
                  $.formUtils.isLoadingModules = false;
                  if (callback && hasLoadedAnyModule) {
                    if( typeof callback === 'function' ) {
                      callback();
                    }
                  }
                }
              };
  
  
            if (numModules > 0) {
              $.formUtils.isLoadingModules = true;
            }
  
            var cacheSuffix = '?_=' + ( new Date().getTime() ),
              appendToElement = document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0];
  
            $.each(moduleList, function (i, modName) {
              modName = $.trim(modName);
              if (modName.length === 0) {
                moduleLoadedCallback();
              }
              else {
                var scriptUrl = path + modName + (modName.slice(-3) === '.js' ? '' : '.js'),
                  script = document.createElement('SCRIPT');
  
                if (scriptUrl in $.formUtils.loadedModules) {
                  // already loaded
                  moduleLoadedCallback();
                }
                else {
  
                  // Remember that this script is loaded
                  $.formUtils.loadedModules[scriptUrl] = 1;
                  hasLoadedAnyModule = true;
  
                  // Load the script
                  script.type = 'text/javascript';
                  script.onload = moduleLoadedCallback;
                  script.src = scriptUrl + ( scriptUrl.slice(-7) === '.dev.js' ? cacheSuffix : '' );
                  script.onerror = function() {
                    $.formUtils.warn('Unable to load form validation module '+scriptUrl);
                  };
                  script.onreadystatechange = function () {
                    // IE 7 fix
                    if (this.readyState === 'complete' || this.readyState === 'loaded') {
                      moduleLoadedCallback();
                      // Handle memory leak in IE
                      this.onload = null;
                      this.onreadystatechange = null;
                    }
                  };
                  appendToElement.appendChild(script);
                }
              }
            });
          };
  
        if (path) {
          loadModuleScripts(modules, path);
        } else {
          var findScriptPathAndLoadModules = function () {
            var foundPath = false;
            $('script[src*="form-validator"]').each(function () {
              foundPath = this.src.substr(0, this.src.lastIndexOf('/')) + '/';
              if (foundPath === '/') {
                foundPath = '';
              }
              return false;
            });
  
            if (foundPath !== false) {
              loadModuleScripts(modules, foundPath);
              return true;
            }
            return false;
          };
  
          if (!findScriptPathAndLoadModules()) {
            $(findScriptPathAndLoadModules);
          }
        }
      }
  
    });
  
  })(jQuery);
  
  /**
   * Setup function for the plugin
   */
  (function ($) {
  
    'use strict';
  
  
    /**
     * A bit smarter split function
     * delimiter can be space, comma, dash or pipe
     * @param {String} val
     * @param {Function|String} [callback]
     * @returns {Array|void}
     */
    $.split = function (val, callback) {
      if (typeof callback !== 'function') {
        // return array
        if (!val) {
          return [];
        }
        var values = [];
        $.each(val.split(callback ? callback : /[,|\-\s]\s*/g),
          function (i, str) {
            str = $.trim(str);
            if (str.length) {
              values.push(str);
            }
          }
        );
        return values;
      } else if (val) {
        // exec callback func on each
        $.each(val.split(/[,|\-\s]\s*/g),
          function (i, str) {
            str = $.trim(str);
            if (str.length) {
              return callback(str, i);
            }
          }
        );
      }
    };
  
    /**
     * Short hand function that makes the validation setup require less code
     * @param conf
     */
    $.validate = function (conf) {
  
      var defaultConf = $.extend($.formUtils.defaultConfig(), {
        form: 'form',
        validateOnEvent: false,
        validateOnBlur: true,
        validateCheckboxRadioOnClick: true,
        showHelpOnFocus: true,
        addSuggestions: true,
        modules: '',
        onModulesLoaded: null,
        language: false,
        onSuccess: false,
        onError: false,
        onElementValidate: false
      });
  
      conf = $.extend(defaultConf, conf || {});
  
      if( conf.lang && conf.lang !== 'en' ) {
        var langModule = 'lang/'+conf.lang+'.js';
        conf.modules += conf.modules.length ? ','+langModule : langModule;
      }
  
      // Add validation to forms
      $(conf.form).each(function (i, form) {
  
        // Make a reference to the config for this form
        form.validationConfig = conf;
  
        // Trigger jQuery event that we're about to setup validation
        var $form = $(form);
        // $.formUtils.$win.trigger('formValidationSetup', [$form, conf]);
        $form.trigger('formValidationSetup', [$form, conf]);
  
        // Remove classes and event handlers that might have been
        // added by a previous call to $.validate
        $form.find('.has-help-txt')
            .unbind('focus.validation')
            .unbind('blur.validation');
  
        $form
          .removeClass('has-validation-callback')
          .unbind('submit.validation')
          .unbind('reset.validation')
          .find('input[data-validation],textarea[data-validation]')
            .unbind('blur.validation');
  
        // Validate when submitted
        $form.bind('submit.validation', function (evt) {
  
          var $form = $(this),
            stop = function() {
              evt.stopImmediatePropagation();
              return false;
            };
  
          if ($.formUtils.haltValidation) {
            // pressing several times on submit button while validation is halted
            return stop();
          }
  
          if ($.formUtils.isLoadingModules) {
            setTimeout(function () {
              $form.trigger('submit.validation');
            }, 200);
            return stop();
          }
  
          var valid = $form.isValid(conf.language, conf);
  
          if ($.formUtils.haltValidation) {
            // Validation got halted by one of the validators
            return stop();
          } else {
            if (valid && typeof conf.onSuccess === 'function') {
              var callbackResponse = conf.onSuccess($form);
              if (callbackResponse === false) {
                return stop();
              }
            } else if (!valid && typeof conf.onError === 'function') {
              conf.onError($form);
              return stop();
            } else {
              return valid ? true : stop();
            }
          }
        })
        .bind('reset.validation', function () {
          $.formUtils.dialogs.removeAllMessagesAndStyling($form, conf);
        })
        .addClass('has-validation-callback');
  
        if (conf.showHelpOnFocus) {
          $form.showHelpOnFocus();
        }
        if (conf.addSuggestions) {
          $form.addSuggestions();
        }
        if (conf.validateOnBlur) {
          $form.validateOnBlur(conf.language, conf);
          $form.bind('html5ValidationAttrsFound', function () {
            $form.validateOnBlur(conf.language, conf);
          });
        }
        if (conf.validateOnEvent) {
          $form.validateOnEvent(conf.language, conf);
        }
      });
  
      if (conf.modules !== '') {
        $.formUtils.loadModules(conf.modules, false, function() {
          if (typeof conf.onModulesLoaded === 'function') {
            conf.onModulesLoaded();
          }
          var $form = typeof conf.form === 'string' ? $(conf.form) : conf.form;
          $.formUtils.$win.trigger('validatorsLoaded', [$form, conf]);
        });
      }
    };
  
  })(jQuery);
  
  /**
   * Utility methods and properties attached to $.formUtils
   */
  (function($, window) {
  
    'use strict';
  
    var $win = $(window);
  
    $.formUtils = $.extend($.formUtils || {}, {
  
      $win: $win,
  
      /**
       * Default config for $(...).isValid();
       */
      defaultConfig: function () {
        return {
          ignore: [], // Names of inputs not to be validated even though `validationRuleAttribute` containing the validation rules tells us to
          errorElementClass: 'error', // Class that will be put on elements which value is invalid
          borderColorOnError: '#b94a48', // Border color of elements which value is invalid, empty string to not change border color
          errorMessageClass: 'form-error', // class name of div containing error messages when validation fails
          validationRuleAttribute: 'data-validation', // name of the attribute holding the validation rules
          validationErrorMsgAttribute: 'data-validation-error-msg', // define custom err msg inline with element
          errorMessagePosition: 'inline', // Can be either "top" or "inline"
          errorMessageTemplate: {
            container: '<div class="{errorMessageClass} alert alert-danger">{messages}</div>',
            messages: '<strong>{errorTitle}</strong><ul>{fields}</ul>',
            field: '<li>{msg}</li>'
          },
          scrollToTopOnError: true,
          dateFormat: 'yyyy-mm-dd',
          addValidClassOnAll: false, // whether or not to apply class="valid" even if the input wasn't validated
          decimalSeparator: '.',
          inputParentClassOnError: 'has-error', // twitter-bootstrap default class name
          inputParentClassOnSuccess: 'has-success', // twitter-bootstrap default class name
          validateHiddenInputs: false, // whether or not hidden inputs should be validated
          inlineErrorMessageCallback: false,
          submitErrorMessageCallback: false
        };
      },
  
      /**
       * Available validators
       */
      validators: {},
  
      /**
       * Events triggered by form validator
       */
      _events: {load: [], valid: [], invalid: []},
  
      /**
       * Setting this property to true during validation will
       * stop further validation from taking place and form will
       * not be sent
       */
      haltValidation: false,
  
      /**
       * This variable will be true $.fn.isValid() is called
       * and false when $.fn.validateOnBlur is called
       */
      isValidatingEntireForm: false,
  
      /**
       * Function for adding a validator
       * @param {Object} validator
       */
      addValidator: function (validator) {
        // prefix with "validate_" for backward compatibility reasons
        var name = validator.name.indexOf('validate_') === 0 ? validator.name : 'validate_' + validator.name;
        if (validator.validateOnKeyUp === undefined) {
          validator.validateOnKeyUp = true;
        }
        this.validators[name] = validator;
      },
  
      /**
       * Warn user via the console if available
       */
      warn: function(msg) {
        if( 'console' in window ) {
          if( typeof window.console.warn === 'function' ) {
            window.console.warn(msg);
          } else if( typeof window.console.log === 'function' ) {
            window.console.log(msg);
          }
        } else {
          alert(msg);
        }
      },
  
      /**
       * Same as input $.fn.val() but also supporting input of typ radio or checkbox
       * @example
       *
       *  $.formUtils.getValue('.myRadioButtons', $('#some-form'));
       *  $.formUtils.getValue($('#some-form').find('.check-boxes'));
       *
       * @param query
       * @param $parent
       * @returns {String|Boolean}
       */
      getValue: function(query, $parent) {
        var $inputs = $parent ? $parent.find(query) : query;
        if ($inputs.length > 0 ) {
          var type = $inputs.eq(0).attr('type');
          if (type === 'radio' || type === 'checkbox') {
            return $inputs.filter(':checked').val();
          } else {
            return $inputs.val();
          }
        }
        return false;
      },
  
      /**
       * Validate the value of given element according to the validation rules
       * found in the attribute data-validation. Will return an object representing
       * a validation result, having the props shouldChangeDisplay, isValid and errorMsg
       * @param {jQuery} $elem
       * @param {Object} language ($.formUtils.LANG)
       * @param {Object} conf
       * @param {jQuery} $form
       * @param {String} [eventContext]
       * @return {Object}
       */
      validateInput: function ($elem, language, conf, $form, eventContext) {
  
        conf = conf || $.formUtils.defaultConfig();
        language = language || $.formUtils.LANG;
  
        var value = this.getValue($elem);
  
        $elem
          .valAttr('skipped', false)
          .one('beforeValidation', function() {
            // Skip input because its hidden or disabled
            // Doing this in a callback makes it possible for others to prevent the default
            // behaviour by binding to the same event and call evt.stopImmediatePropagation()
            if ($elem.attr('disabled') || (!$elem.is(':visible') && !conf.validateHiddenInputs)) {
              $elem.valAttr('skipped', 1);
            }
          })
          .trigger('beforeValidation', [value, conf, language]);
  
  
        var inputIsOptional = $elem.valAttr('optional') === 'true',
            skipBecauseItsEmpty = !value && inputIsOptional,
            validationRules = $elem.attr(conf.validationRuleAttribute),
            isValid = true,
            errorMsg = '',
            result = {isValid: true, shouldChangeDisplay:true, errorMsg:''};
  
        // For input type="number", browsers attempt to parse the entered value into a number.
        // If the input is not numeric, browsers handle the situation differently:
        // Chrome 48 simply disallows non-numeric input; FF 44 clears out the input box on blur;
        // Safari 5 parses the entered string to find a leading number.
        // If the input fails browser validation, the browser sets the input value equal to an empty string.
        // Therefore, we cannot distinguish (apart from hacks) between an empty input type="text" and one with a
        // value that can't be parsed by the browser.
  
        if (!validationRules || skipBecauseItsEmpty || $elem.valAttr('skipped')) {
          result.shouldChangeDisplay = conf.addValidClassOnAll;
          return result;
        }
  
        // Filter out specified characters
        var ignore = $elem.valAttr('ignore');
        if (ignore) {
          $.each(ignore.split(''), function(i, char) {
            value = value.replace(new RegExp('\\'+char), '');
          });
        }
  
        $.split(validationRules, function (rule) {
  
          if (rule.indexOf('validate_') !== 0) {
            rule = 'validate_' + rule;
          }
  
          var validator = $.formUtils.validators[rule];
  
          if (validator) {
  
            // special change of element for checkbox_group rule
            if (rule === 'validate_checkbox_group') {
              // set element to first in group, so error msg attr doesn't need to be set on all elements in group
              $elem = $form.find('[name="' + $elem.attr('name') + '"]:eq(0)');
            }
  
            if (eventContext !== 'keyup' || validator.validateOnKeyUp) {
              // A validator can prevent itself from getting triggered on keyup
              isValid = validator.validatorFunction(value, $elem, conf, language, $form);
            }
  
            if (!isValid) {
              errorMsg = $.formUtils.dialogs.resolveErrorMessage($elem, validator, rule, conf, language);
              return false; // break iteration
            }
  
          } else {
  
            // todo: Add some validator lookup function and tell immediately which module is missing
            throw new Error('Using undefined validator "' + rule +
              '". Maybe you have forgotten to load the module that "' + rule +'" belongs to?');
  
          }
  
        }, ' ');
  
  
        if (isValid === false) {
          $elem.trigger('validation', false);
          result.errorMsg = errorMsg;
          result.isValid = false;
          result.shouldChangeDisplay = true;
        } else if (isValid === null) {
          // A validatorFunction returning null means that it's not able to validate
          // the input at this time. Most probably some async stuff need to gets finished
          // first and then the validator will re-trigger the validation.
          result.shouldChangeDisplay = false;
        } else {
          $elem.trigger('validation', true);
          result.shouldChangeDisplay = true;
        }
  
        // Run element validation callback
        if (typeof conf.onElementValidate === 'function' && errorMsg !== null) {
          conf.onElementValidate(result.isValid, $elem, $form, errorMsg);
        }
  
        $elem.trigger('afterValidation', [result, eventContext]);
  
        return result;
      },
  
      /**
       * Is it a correct date according to given dateFormat. Will return false if not, otherwise
       * an array 0=>year 1=>month 2=>day
       *
       * @param {String} val
       * @param {String} dateFormat
       * @param {Boolean} [addMissingLeadingZeros]
       * @return {Array}|{Boolean}
       */
      parseDate: function (val, dateFormat, addMissingLeadingZeros) {
        var divider = dateFormat.replace(/[a-zA-Z]/gi, '').substring(0, 1),
          regexp = '^',
          formatParts = dateFormat.split(divider || null),
          matches, day, month, year;
  
        $.each(formatParts, function (i, part) {
          regexp += (i > 0 ? '\\' + divider : '') + '(\\d{' + part.length + '})';
        });
  
        regexp += '$';
  
        if (addMissingLeadingZeros) {
          var newValueParts = [];
          $.each(val.split(divider), function(i, part) {
            if(part.length === 1) {
              part = '0'+part;
            }
            newValueParts.push(part);
          });
          val = newValueParts.join(divider);
        }
  
        matches = val.match(new RegExp(regexp));
        if (matches === null) {
          return false;
        }
  
        var findDateUnit = function (unit, formatParts, matches) {
          for (var i = 0; i < formatParts.length; i++) {
            if (formatParts[i].substring(0, 1) === unit) {
              return $.formUtils.parseDateInt(matches[i + 1]);
            }
          }
          return -1;
        };
  
        month = findDateUnit('m', formatParts, matches);
        day = findDateUnit('d', formatParts, matches);
        year = findDateUnit('y', formatParts, matches);
  
        if ((month === 2 && day > 28 && (year % 4 !== 0 || year % 100 === 0 && year % 400 !== 0)) ||
          (month === 2 && day > 29 && (year % 4 === 0 || year % 100 !== 0 && year % 400 === 0)) ||
          month > 12 || month === 0) {
          return false;
        }
        if ((this.isShortMonth(month) && day > 30) || (!this.isShortMonth(month) && day > 31) || day === 0) {
          return false;
        }
  
        return [year, month, day];
      },
  
      /**
       * skum fix. är talet 05 eller lägre ger parseInt rätt int annars får man 0 när man kör parseInt?
       *
       * @param {String} val
       * @return {Number}
       */
      parseDateInt: function (val) {
        if (val.indexOf('0') === 0) {
          val = val.replace('0', '');
        }
        return parseInt(val, 10);
      },
  
      /**
       * Has month only 30 days?
       *
       * @param {Number} m
       * @return {Boolean}
       */
      isShortMonth: function (m) {
        return (m % 2 === 0 && m < 7) || (m % 2 !== 0 && m > 7);
      },
  
      /**
       * Restrict input length
       *
       * @param {jQuery} $inputElement Jquery Html object
       * @param {jQuery} $maxLengthElement jQuery Html Object
       * @return void
       */
      lengthRestriction: function ($inputElement, $maxLengthElement) {
        // read maxChars from counter display initial text value
        var maxChars = parseInt($maxLengthElement.text(), 10),
          charsLeft = 0,
  
        // internal function does the counting and sets display value
          countCharacters = function () {
            var numChars = $inputElement.val().length;
            if (numChars > maxChars) {
              // get current scroll bar position
              var currScrollTopPos = $inputElement.scrollTop();
              // trim value to max length
              $inputElement.val($inputElement.val().substring(0, maxChars));
              $inputElement.scrollTop(currScrollTopPos);
            }
            charsLeft = maxChars - numChars;
            if (charsLeft < 0) {
              charsLeft = 0;
            }
  
            // set counter text
            $maxLengthElement.text(charsLeft);
          };
  
        // bind events to this element
        // setTimeout is needed, cut or paste fires before val is available
        $($inputElement).bind('keydown keyup keypress focus blur', countCharacters)
          .bind('cut paste', function () {
            setTimeout(countCharacters, 100);
          });
  
        // count chars on pageload, if there are prefilled input-values
        $(document).bind('ready', countCharacters);
      },
  
      /**
       * Test numeric against allowed range
       *
       * @param $value int
       * @param $rangeAllowed str; (1-2, min1, max2, 10)
       * @return array
       */
      numericRangeCheck: function (value, rangeAllowed) {
        // split by dash
        var range = $.split(rangeAllowed),
        // min or max
          minmax = parseInt(rangeAllowed.substr(3), 10);
  
        if( range.length === 1 && rangeAllowed.indexOf('min') === -1 && rangeAllowed.indexOf('max') === -1 ) {
          range = [rangeAllowed, rangeAllowed]; // only a number, checking agains an exact number of characters
        }
  
        // range ?
        if (range.length === 2 && (value < parseInt(range[0], 10) || value > parseInt(range[1], 10) )) {
          return [ 'out', range[0], range[1] ];
        } // value is out of range
        else if (rangeAllowed.indexOf('min') === 0 && (value < minmax )) // min
        {
          return ['min', minmax];
        } // value is below min
        else if (rangeAllowed.indexOf('max') === 0 && (value > minmax )) // max
        {
          return ['max', minmax];
        } // value is above max
        // since no other returns executed, value is in allowed range
        return [ 'ok' ];
      },
  
  
      _numSuggestionElements: 0,
      _selectedSuggestion: null,
      _previousTypedVal: null,
  
      /**
       * Utility function that can be used to create plugins that gives
       * suggestions when inputs is typed into
       * @param {jQuery} $elem
       * @param {Array} suggestions
       * @param {Object} settings - Optional
       * @return {jQuery}
       */
      suggest: function ($elem, suggestions, settings) {
        var conf = {
            css: {
              maxHeight: '150px',
              background: '#FFF',
              lineHeight: '150%',
              textDecoration: 'underline',
              overflowX: 'hidden',
              overflowY: 'auto',
              border: '#CCC solid 1px',
              borderTop: 'none',
              cursor: 'pointer'
            },
            activeSuggestionCSS: {
              background: '#E9E9E9'
            }
          },
          setSuggsetionPosition = function ($suggestionContainer, $input) {
            var offset = $input.offset();
            $suggestionContainer.css({
              width: $input.outerWidth(),
              left: offset.left + 'px',
              top: (offset.top + $input.outerHeight()) + 'px'
            });
          };
  
        if (settings) {
          $.extend(conf, settings);
        }
  
        conf.css.position = 'absolute';
        conf.css['z-index'] = 9999;
        $elem.attr('autocomplete', 'off');
  
        if (this._numSuggestionElements === 0) {
          // Re-position suggestion container if window size changes
          $win.bind('resize', function () {
            $('.jquery-form-suggestions').each(function () {
              var $container = $(this),
                suggestID = $container.attr('data-suggest-container');
              setSuggsetionPosition($container, $('.suggestions-' + suggestID).eq(0));
            });
          });
        }
  
        this._numSuggestionElements++;
  
        var onSelectSuggestion = function ($el) {
          var suggestionId = $el.valAttr('suggestion-nr');
          $.formUtils._selectedSuggestion = null;
          $.formUtils._previousTypedVal = null;
          $('.jquery-form-suggestion-' + suggestionId).fadeOut('fast');
        };
  
        $elem
          .data('suggestions', suggestions)
          .valAttr('suggestion-nr', this._numSuggestionElements)
          .unbind('focus.suggest')
          .bind('focus.suggest', function () {
            $(this).trigger('keyup');
            $.formUtils._selectedSuggestion = null;
          })
          .unbind('keyup.suggest')
          .bind('keyup.suggest', function () {
            var $input = $(this),
              foundSuggestions = [],
              val = $.trim($input.val()).toLocaleLowerCase();
  
            if (val === $.formUtils._previousTypedVal) {
              return;
            }
            else {
              $.formUtils._previousTypedVal = val;
            }
  
            var hasTypedSuggestion = false,
              suggestionId = $input.valAttr('suggestion-nr'),
              $suggestionContainer = $('.jquery-form-suggestion-' + suggestionId);
  
            $suggestionContainer.scrollTop(0);
  
            // Find the right suggestions
            if (val !== '') {
              var findPartial = val.length > 2;
              $.each($input.data('suggestions'), function (i, suggestion) {
                var lowerCaseVal = suggestion.toLocaleLowerCase();
                if (lowerCaseVal === val) {
                  foundSuggestions.push('<strong>' + suggestion + '</strong>');
                  hasTypedSuggestion = true;
                  return false;
                } else if (lowerCaseVal.indexOf(val) === 0 || (findPartial && lowerCaseVal.indexOf(val) > -1)) {
                  foundSuggestions.push(suggestion.replace(new RegExp(val, 'gi'), '<strong>$&</strong>'));
                }
              });
            }
  
            // Hide suggestion container
            if (hasTypedSuggestion || (foundSuggestions.length === 0 && $suggestionContainer.length > 0)) {
              $suggestionContainer.hide();
            }
  
            // Create suggestion container if not already exists
            else if (foundSuggestions.length > 0 && $suggestionContainer.length === 0) {
              $suggestionContainer = $('<div></div>').css(conf.css).appendTo('body');
              $elem.addClass('suggestions-' + suggestionId);
              $suggestionContainer
                .attr('data-suggest-container', suggestionId)
                .addClass('jquery-form-suggestions')
                .addClass('jquery-form-suggestion-' + suggestionId);
            }
  
            // Show hidden container
            else if (foundSuggestions.length > 0 && !$suggestionContainer.is(':visible')) {
              $suggestionContainer.show();
            }
  
            // add suggestions
            if (foundSuggestions.length > 0 && val.length !== foundSuggestions[0].length) {
  
              // put container in place every time, just in case
              setSuggsetionPosition($suggestionContainer, $input);
  
              // Add suggestions HTML to container
              $suggestionContainer.html('');
              $.each(foundSuggestions, function (i, text) {
                $('<div></div>')
                  .append(text)
                  .css({
                    overflow: 'hidden',
                    textOverflow: 'ellipsis',
                    whiteSpace: 'nowrap',
                    padding: '5px'
                  })
                  .addClass('form-suggest-element')
                  .appendTo($suggestionContainer)
                  .click(function () {
                    $input.focus();
                    $input.val($(this).text());
                    $input.trigger('change');
                    onSelectSuggestion($input);
                  });
              });
            }
          })
          .unbind('keydown.validation')
          .bind('keydown.validation', function (e) {
            var code = (e.keyCode ? e.keyCode : e.which),
              suggestionId,
              $suggestionContainer,
              $input = $(this);
  
            if (code === 13 && $.formUtils._selectedSuggestion !== null) {
              suggestionId = $input.valAttr('suggestion-nr');
              $suggestionContainer = $('.jquery-form-suggestion-' + suggestionId);
              if ($suggestionContainer.length > 0) {
                var newText = $suggestionContainer.find('div').eq($.formUtils._selectedSuggestion).text();
                $input.val(newText);
                $input.trigger('change');
                onSelectSuggestion($input);
                e.preventDefault();
              }
            }
            else {
              suggestionId = $input.valAttr('suggestion-nr');
              $suggestionContainer = $('.jquery-form-suggestion-' + suggestionId);
              var $suggestions = $suggestionContainer.children();
              if ($suggestions.length > 0 && $.inArray(code, [38, 40]) > -1) {
                if (code === 38) { // key up
                  if ($.formUtils._selectedSuggestion === null) {
                    $.formUtils._selectedSuggestion = $suggestions.length - 1;
                  }
                  else{
                    $.formUtils._selectedSuggestion--;
                  }
                  if ($.formUtils._selectedSuggestion < 0) {
                    $.formUtils._selectedSuggestion = $suggestions.length - 1;
                  }
                }
                else if (code === 40) { // key down
                  if ($.formUtils._selectedSuggestion === null) {
                    $.formUtils._selectedSuggestion = 0;
                  }
                  else {
                    $.formUtils._selectedSuggestion++;
                  }
                  if ($.formUtils._selectedSuggestion > ($suggestions.length - 1)) {
                    $.formUtils._selectedSuggestion = 0;
                  }
                }
  
                // Scroll in suggestion window
                var containerInnerHeight = $suggestionContainer.innerHeight(),
                  containerScrollTop = $suggestionContainer.scrollTop(),
                  suggestionHeight = $suggestionContainer.children().eq(0).outerHeight(),
                  activeSuggestionPosY = suggestionHeight * ($.formUtils._selectedSuggestion);
  
                if (activeSuggestionPosY < containerScrollTop || activeSuggestionPosY > (containerScrollTop + containerInnerHeight)) {
                  $suggestionContainer.scrollTop(activeSuggestionPosY);
                }
  
                $suggestions
                  .removeClass('active-suggestion')
                  .css('background', 'none')
                  .eq($.formUtils._selectedSuggestion)
                  .addClass('active-suggestion')
                  .css(conf.activeSuggestionCSS);
  
                e.preventDefault();
                return false;
              }
            }
          })
          .unbind('blur.suggest')
          .bind('blur.suggest', function () {
            onSelectSuggestion($(this));
          });
  
        return $elem;
      },
  
      /**
       * Error dialogs
       *
       * @var {Object}
       */
      LANG: {
        errorTitle: 'Form submission failed!',
        requiredField: 'Bu alan boş geçilemez!',
        requiredFields: 'You have not answered all required fields',
        badTime: 'You have not given a correct time',
        badEmail: 'Bu geçerli bir e-posta adresi değil',
        badTelephone: 'You have not given a correct phone number',
        badSecurityAnswer: 'You have not given a correct answer to the security question',
        badDate: 'You have not given a correct date',
        lengthBadStart: 'The input value must be between ',
        lengthBadEnd: ' characters',
        lengthTooLongStart: 'The input value is longer than ',
        lengthTooShortStart: 'Şifre en az 6 karakter, bir küçük bir büyük ve rakamlardan oluşmak zorundadır',
        notConfirmed: 'Input values could not be confirmed',
        badDomain: 'Incorrect domain value',
        badUrl: 'Bu geçerli bir website adresi değil',
        badCustomVal: 'The input value is incorrect',
        andSpaces: ' and spaces ',
        badInt: 'The input value was not a correct number',
        badSecurityNumber: 'Your social security number was incorrect',
        badUKVatAnswer: 'Incorrect UK VAT Number',
        badUKNin: 'Incorrect UK NIN',
        badUKUtr: 'Incorrect UK UTR Number',
        badStrength: 'Şifre en az 6 karakter, bir küçük bir büyük ve rakamlardan oluşmak zorundadır',
        badNumberOfSelectedOptionsStart: 'You have to choose at least ',
        badNumberOfSelectedOptionsEnd: ' answers',
        badAlphaNumeric: 'The input value can only contain alphanumeric characters ',
        badAlphaNumericExtra: ' and ',
        wrongFileSize: 'The file you are trying to upload is too large (max %s)',
        wrongFileType: 'Only files of type %s is allowed',
        groupCheckedRangeStart: 'Please choose between ',
        groupCheckedTooFewStart: 'Please choose at least ',
        groupCheckedTooManyStart: 'Please choose a maximum of ',
        groupCheckedEnd: ' item(s)',
        badCreditCard: 'The credit card number is not correct',
        badCVV: 'Yanlış gün sayısı girdiniz !',
        wrongFileDim : 'Incorrect image dimensions,',
        imageTooTall : 'the image can not be taller than',
        imageTooWide : 'the image can not be wider than',
        imageTooSmall : 'the image was too small',
        min : 'min',
        max : 'max',
        imageRatioNotAccepted : 'Image ratio is not be accepted',
        badBrazilTelephoneAnswer: 'The phone number entered is invalid',
        badBrazilCEPAnswer: 'The CEP entered is invalid',
        badBrazilCPFAnswer: 'The CPF entered is invalid',
        badPlPesel: 'The PESEL entered is invalid',
        badPlNip: 'The NIP entered is invalid',
        badPlRegon: 'The REGON entered is invalid',
        badreCaptcha: 'Please confirm that you are not a bot',
  	  badImage: 'Sadece jpeg veya png seçebilirsiniz'
      }
    });
  
  })(jQuery, window);
  
  /**
   * File declaring all default validators.
   */
  (function($) {
  
    /*
     * Validate email
     */
    $.formUtils.addValidator({
      name: 'email',
      validatorFunction: function (email) {
  
        var emailParts = email.toLowerCase().split('@'),
          localPart = emailParts[0],
          domain = emailParts[1];
  
        if (localPart && domain) {
  
          if( localPart.indexOf('"') === 0 ) {
            var len = localPart.length;
            localPart = localPart.replace(/\"/g, '');
            if( localPart.length !== (len-2) ) {
              return false; // It was not allowed to have more than two apostrophes
            }
          }
  
          return $.formUtils.validators.validate_domain.validatorFunction(emailParts[1]) &&
            localPart.indexOf('.') !== 0 &&
            localPart.substring(localPart.length-1, localPart.length) !== '.' &&
            localPart.indexOf('..') === -1 &&
            !(/[^\w\+\.\-\#\-\_\~\!\$\&\'\(\)\*\+\,\;\=\:]/.test(localPart));
        }
  
        return false;
      },
      errorMessage: '',
      errorMessageKey: 'badEmail'
    });
    
    
  
    /*
     * Validate domain name
     */
    $.formUtils.addValidator({
      name: 'domain',
      validatorFunction: function (val) {
        return val.length > 0 &&
          val.length <= 253 && // Including sub domains
          !(/[^a-zA-Z0-9]/.test(val.slice(-2))) && !(/[^a-zA-Z0-9]/.test(val.substr(0, 1))) && !(/[^a-zA-Z0-9\.\-]/.test(val)) &&
          val.split('..').length === 1 &&
          val.split('.').length > 1;
      },
      errorMessage: '',
      errorMessageKey: 'badDomain'
    });
  
    /*
     * Validate required
     */
    $.formUtils.addValidator({
      name: 'required',
      validatorFunction: function (val, $el, config, language, $form) {
        switch ($el.attr('type')) {
          case 'checkbox':
            return $el.is(':checked');
          case 'radio':
            return $form.find('input[name="' + $el.attr('name') + '"]').filter(':checked').length > 0;
          default:
            return $.trim(val) !== '';
        }
      },
      errorMessage: '',
      errorMessageKey: function(config) {
        if (config.errorMessagePosition === 'top' || typeof config.errorMessagePosition === 'function') {
          return 'requiredFields';
        }
        else {
          return 'requiredField';
        }
      }
    });
  
    /*
     * Validate length range
     */
    $.formUtils.addValidator({
      name: 'length',
      validatorFunction: function (val, $el, conf, lang) {
        var lengthAllowed = $el.valAttr('length'),
          type = $el.attr('type');
  
        if (lengthAllowed === undefined) {
          alert('Please add attribute "data-validation-length" to ' + $el[0].nodeName + ' named ' + $el.attr('name'));
          return true;
        }
  
        // check if length is above min, below max or within range.
        var len = type === 'file' && $el.get(0).files !== undefined ? $el.get(0).files.length : val.length,
          lengthCheckResults = $.formUtils.numericRangeCheck(len, lengthAllowed),
          checkResult;
  
        switch (lengthCheckResults[0]) {   // outside of allowed range
          case 'out':
            this.errorMessage = lang.lengthBadStart + lengthAllowed + lang.lengthBadEnd;
            checkResult = false;
            break;
          // too short
          case 'min':
            this.errorMessage = lang.lengthTooShortStart;
            checkResult = false;
            break;
          // too long
          case 'max':
            this.errorMessage = lang.lengthTooLongStart + lengthCheckResults[1] + lang.lengthBadEnd;
            checkResult = false;
            break;
          // ok
          default:
            checkResult = true;
        }
  
        return checkResult;
      },
      errorMessage: '',
      errorMessageKey: ''
    });
  
    /*
     * Validate url
     */
    $.formUtils.addValidator({
      name: 'password',
      validatorFunction: function (password) {
  
        var urlFilter = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[0-9a-zA-Z]{6,}$/;	  
        if (urlFilter.test(password)) return 'requiredField';
        return false;   
      },
      errorMessage: '',
      errorMessageKey: 'badStrength'
    });
    
    
    
  	$.formUtils.addValidator({
  		name: 'emaill',
  		validatorFunction: function (emaill) {
  		  var urlFilter = /^[a-z0-9\_\.\-]{5,40}([a-z0-9])@([a-z0-9]{2,20}\.)+([a-z]{2,4}|[a-z]{2,4}\.[A-Za-z]{2,4})$/;	  
  		  if (urlFilter.test(emaill)) return 'requiredField';
  		  return false;   
  		},
  		errorMessage: '',
  		errorMessageKey: 'badEmail'
  	});
  	$.formUtils.addValidator({
      name: 'url',
      validatorFunction: function (url) {
     
  
        var urlFilter = /^(http[s]?:\/\/)?(www\.)([a-z0-9]+)\.[a-z]{2,5}(\.[a-z]{2})?$/;
        if (urlFilter.test(url)) return 'requiredField';
  		  return false;   
       
      },
      errorMessage: '',
      errorMessageKey: 'badUrl'
    });
    	$.formUtils.addValidator({
      name: 'gun',
      validatorFunction: function (gun) {
     
  
  	var urlFilter = /^([2-3]{1}[0-9]{1}|40)$/;
        if (urlFilter.test(gun)) return 'requiredField';
  		  return false;   
       
      },
      errorMessage: '',
      errorMessageKey: 'badCVV'
    });
  	
  	$.formUtils.addValidator({
  		name: 'imagee',
  		validatorFunction: function (imagee) {
  
  		  var urlFilter =  /\.(gif|jpg|jpeg|png)$/i;	  
  		  if (urlFilter.test(imagee)) return 'requiredField';
  		  return false;   
  		},
  		errorMessage: '',
  		errorMessageKey: 'badImage'
  	});
  	  
  
    /*
     * Validate number (floating or integer)
     */
    $.formUtils.addValidator({
      name: 'number',
      validatorFunction: function (val, $el, conf) {
        if (val !== '') {
          var allowing = $el.valAttr('allowing') || '',
            decimalSeparator = $el.valAttr('decimal-separator') || conf.decimalSeparator,
            allowsRange = false,
            begin, end,
            steps = $el.valAttr('step') || '',
            allowsSteps = false,
            sanitize = $el.attr('data-sanitize') || '',
            isFormattedWithNumeral = sanitize.match(/(^|[\s])numberFormat([\s]|$)/i);
  
          if (isFormattedWithNumeral) {
            if (!window.numeral) {
              throw new ReferenceError('The data-sanitize value numberFormat cannot be used without the numeral' +
                ' library. Please see Data Validation in http://www.formvalidator.net for more information.');
            }
            //Unformat input first, then convert back to String
            if (val.length) {
              val = String(numeral().unformat(val));
            }
          }
  
          if (allowing.indexOf('number') === -1) {
            allowing += ',number';
          }
  
          if (allowing.indexOf('negative') === -1 && val.indexOf('-') === 0) {
            return false;
          }
  
          if (allowing.indexOf('range') > -1) {
            begin = parseFloat(allowing.substring(allowing.indexOf('[') + 1, allowing.indexOf(';')));
            end = parseFloat(allowing.substring(allowing.indexOf(';') + 1, allowing.indexOf(']')));
            allowsRange = true;
          }
  
          if (steps !== '') {
            allowsSteps = true;
          }
  
          if (decimalSeparator === ',') {
            if (val.indexOf('.') > -1) {
              return false;
            }
            // Fix for checking range with floats using ,
            val = val.replace(',', '.');
          }
          if (val.replace(/[0-9-]/g, '') === '' && (!allowsRange || (val >= begin && val <= end)) && (!allowsSteps || (val % steps === 0))) {
            return true;
          }
  
          if (allowing.indexOf('float') > -1 && val.match(new RegExp('^([0-9-]+)\\.([0-9]+)$')) !== null && (!allowsRange || (val >= begin && val <= end)) && (!allowsSteps || (val % steps === 0))) {
            return true;
          }
        }
        return false;
      },
      errorMessage: '',
      errorMessageKey: 'badInt'
    });
  
    /*
     * Validate alpha numeric
     */
    $.formUtils.addValidator({
      name: 'alphanumeric',
      validatorFunction: function (val, $el, conf, language) {
        var patternStart = '^([a-zA-Z0-9',
          patternEnd = ']+)$',
          additionalChars = $el.valAttr('allowing'),
          pattern = '';
  
        if (additionalChars) {
          pattern = patternStart + additionalChars + patternEnd;
          var extra = additionalChars.replace(/\\/g, '');
          if (extra.indexOf(' ') > -1) {
            extra = extra.replace(' ', '');
            extra += language.andSpaces || $.formUtils.LANG.andSpaces;
          }
          this.errorMessage = language.badAlphaNumeric + language.badAlphaNumericExtra + extra;
        } else {
          pattern = patternStart + patternEnd;
          this.errorMessage = language.badAlphaNumeric;
        }
  
        return new RegExp(pattern).test(val);
      },
      errorMessage: '',
      errorMessageKey: ''
    });
  
    /*
     * Validate against regexp
     */
    $.formUtils.addValidator({
      name: 'custom',
      validatorFunction: function (val, $el) {
        var regexp = new RegExp($el.valAttr('regexp'));
        return regexp.test(val);
      },
      errorMessage: '',
      errorMessageKey: 'badCustomVal'
    });
  
    /*
     * Validate date
     */
    $.formUtils.addValidator({
      name: 'date',
      validatorFunction: function (date, $el, conf) {
        var dateFormat = $el.valAttr('format') || conf.dateFormat || 'yyyy-mm-dd',
          addMissingLeadingZeros = $el.valAttr('require-leading-zero') === 'false';
        return $.formUtils.parseDate(date, dateFormat, addMissingLeadingZeros) !== false;
      },
      errorMessage: '',
      errorMessageKey: 'badDate'
    });
  
  
    /*
     * Validate group of checkboxes, validate qty required is checked
     * written by Steve Wasiura : http://stevewasiura.waztech.com
     * element attrs
     *    data-validation="checkbox_group"
     *    data-validation-qty="1-2"  // min 1 max 2
     *    data-validation-error-msg="chose min 1, max of 2 checkboxes"
     */
    $.formUtils.addValidator({
      name: 'checkbox_group',
      validatorFunction: function (val, $el, conf, lang, $form) {
        // preset return var
        var isValid = true,
        // get name of element. since it is a checkbox group, all checkboxes will have same name
          elname = $el.attr('name'),
        // get checkboxes and count the checked ones
          $checkBoxes = $('input[type=checkbox][name^="' + elname + '"]', $form),
          checkedCount = $checkBoxes.filter(':checked').length,
        // get el attr that specs qty required / allowed
          qtyAllowed = $el.valAttr('qty');
  
        if (qtyAllowed === undefined) {
          var elementType = $el.get(0).nodeName;
          alert('Attribute "data-validation-qty" is missing from ' + elementType + ' named ' + $el.attr('name'));
        }
  
        // call Utility function to check if count is above min, below max, within range etc.
        var qtyCheckResults = $.formUtils.numericRangeCheck(checkedCount, qtyAllowed);
  
        // results will be array, [0]=result str, [1]=qty int
        switch (qtyCheckResults[0]) {
          // outside allowed range
          case 'out':
            this.errorMessage = lang.groupCheckedRangeStart + qtyAllowed + lang.groupCheckedEnd;
            isValid = false;
            break;
          // below min qty
          case 'min':
            this.errorMessage = lang.groupCheckedTooFewStart + qtyCheckResults[1] + lang.groupCheckedEnd;
            isValid = false;
            break;
          // above max qty
          case 'max':
            this.errorMessage = lang.groupCheckedTooManyStart + qtyCheckResults[1] + lang.groupCheckedEnd;
            isValid = false;
            break;
          // ok
          default:
            isValid = true;
        }
  
        if( !isValid ) {
          var _triggerOnBlur = function() {
            $checkBoxes.unbind('click', _triggerOnBlur);
            $checkBoxes.filter('*[data-validation]').validateInputOnBlur(lang, conf, false, 'blur');
          };
          $checkBoxes.bind('click', _triggerOnBlur);
        }
  
        return isValid;
      }
      //   errorMessage : '', // set above in switch statement
      //   errorMessageKey: '' // not used
    });
  
  })(jQuery);
  
  
  }));
  