text: /*!
   * Copyright (c) 2014 Chris O'Hara <cohara87@gmail.com>
   *
   * 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 (name, definition) {
      if (typeof exports !== 'undefined' && typeof module !== 'undefined') {
          module.exports = definition();
      } else if (typeof define === 'function' && typeof define.amd === 'object') {
          define(definition);
      } else {
          this[name] = definition();
      }
  })('validator', function (validator) {
  
      'use strict';
  
      validator = { version: '3.24.0' };
  
      var email = /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i;
  
      var creditCard = /^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11})$/;
  
      var isbn10Maybe = /^(?:[0-9]{9}X|[0-9]{10})$/
        , isbn13Maybe = /^(?:[0-9]{13})$/;
  
      var ipv4Maybe = /^(\d?\d?\d)\.(\d?\d?\d)\.(\d?\d?\d)\.(\d?\d?\d)$/
        , ipv6 = /^::|^::1|^([a-fA-F0-9]{1,4}::?){1,7}([a-fA-F0-9]{1,4})$/;
  
      var uuid = {
          '3': /^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i
        , '4': /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i
        , '5': /^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i
        , all: /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i
      };
  
      var alpha = /^[a-zA-Z]+$/
        , alphanumeric = /^[a-zA-Z0-9]+$/
        , numeric = /^-?[0-9]+$/
        , int = /^(?:-?(?:0|[1-9][0-9]*))$/
        , float = /^(?:-?(?:[0-9]+))?(?:\.[0-9]*)?(?:[eE][\+\-]?(?:[0-9]+))?$/
        , hexadecimal = /^[0-9a-fA-F]+$/
        , hexcolor = /^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;
  
      var ascii = /^[\x00-\x7F]+$/
        , multibyte = /[^\x00-\x7F]/
        , fullWidth = /[^\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]/
        , halfWidth = /[\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]/;
  
      var surrogatePair = /[\uD800-\uDBFF][\uDC00-\uDFFF]/;
  
      var base64 = /^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{4})$/;
  
      validator.extend = function (name, fn) {
          validator[name] = function () {
              var args = Array.prototype.slice.call(arguments);
              args[0] = validator.toString(args[0]);
              return fn.apply(validator, args);
          };
      };
  
      //Right before exporting the validator object, pass each of the builtins
      //through extend() so that their first argument is coerced to a string
      validator.init = function () {
          for (var name in validator) {
              if (typeof validator[name] !== 'function' || name === 'toString' ||
                      name === 'toDate' || name === 'extend' || name === 'init') {
                  continue;
              }
              validator.extend(name, validator[name]);
          }
      };
  
      validator.toString = function (input) {
          if (typeof input === 'object' && input !== null && input.toString) {
              input = input.toString();
          } else if (input === null || typeof input === 'undefined' || (isNaN(input) && !input.length)) {
              input = '';
          } else if (typeof input !== 'string') {
              input += '';
          }
          return input;
      };
  
      validator.toDate = function (date) {
          if (Object.prototype.toString.call(date) === '[object Date]') {
              return date;
          }
          date = Date.parse(date);
          return !isNaN(date) ? new Date(date) : null;
      };
  
      validator.toFloat = function (str) {
          return parseFloat(str);
      };
  
      validator.toInt = function (str, radix) {
          return parseInt(str, radix || 10);
      };
  
      validator.toBoolean = function (str, strict) {
          if (strict) {
              return str === '1' || str === 'true';
          }
          return str !== '0' && str !== 'false' && str !== '';
      };
  
      validator.equals = function (str, comparison) {
          return str === validator.toString(comparison);
      };
  
      validator.contains = function (str, elem) {
          return str.indexOf(validator.toString(elem)) >= 0;
      };
  
      validator.matches = function (str, pattern, modifiers) {
          if (Object.prototype.toString.call(pattern) !== '[object RegExp]') {
              pattern = new RegExp(pattern, modifiers);
          }
          return pattern.test(str);
      };
  
      validator.isEmail = function (str) {
          return email.test(str);
      };
  
      var default_url_options = {
          protocols: [ 'http', 'https', 'ftp' ]
        , require_tld: true
        , require_protocol: false
        , allow_underscores: false
        , allow_trailing_dot: false
      };
  
      validator.isURL = function (url, options) {
          if (!url || url.length >= 2083) {
              return false;
          }
          if (url.indexOf('mailto:') === 0) {
              return false;
          }
          options = merge(options, default_url_options);
          var protocol, user, pass, auth, host, hostname, port,
              port_str, path, query, hash, split;
          split = url.split('://');
          if (split.length > 1) {
              protocol = split.shift();
              if (options.protocols.indexOf(protocol) === -1) {
                  return false;
              }
          } else if (options.require_protocol) {
              return false;
          }
          url = split.join('://');
          split = url.split('#');
          url = split.shift();
          hash = split.join('#');
          if (hash && /\s/.test(hash)) {
              return false;
          }
          split = url.split('?');
          url = split.shift();
          query = split.join('?');
          if (query && /\s/.test(query)) {
              return false;
          }
          split = url.split('/');
          url = split.shift();
          path = split.join('/');
          if (path && /\s/.test(path)) {
              return false;
          }
          split = url.split('@');
          if (split.length > 1) {
              auth = split.shift();
              if (auth.indexOf(':') >= 0) {
                  auth = auth.split(':');
                  user = auth.shift();
                  if (!/^\S+$/.test(user)) {
                      return false;
                  }
                  pass = auth.join(':');
                  if (!/^\S*$/.test(user)) {
                      return false;
                  }
              }
          }
          hostname = split.join('@');
          split = hostname.split(':');
          host = split.shift();
          if (split.length) {
              port_str = split.join(':');
              port = parseInt(port_str, 10);
              if (!/^[0-9]+$/.test(port_str) || port <= 0 || port > 65535) {
                  return false;
              }
          }
          if (!validator.isIP(host) && !validator.isFQDN(host, options) &&
                  host !== 'localhost') {
              return false;
          }
          if (options.host_whitelist &&
                  options.host_whitelist.indexOf(host) === -1) {
              return false;
          }
          if (options.host_blacklist &&
                  options.host_blacklist.indexOf(host) !== -1) {
              return false;
          }
          return true;
      };
  
      validator.isIP = function (str, version) {
          version = validator.toString(version);
          if (!version) {
              return validator.isIP(str, 4) || validator.isIP(str, 6);
          } else if (version === '4') {
              if (!ipv4Maybe.test(str)) {
                  return false;
              }
              var parts = str.split('.').sort(function (a, b) {
                  return a - b;
              });
              return parts[3] <= 255;
          }
          return version === '6' && ipv6.test(str);
      };
  
      var default_fqdn_options = {
          require_tld: true
        , allow_underscores: false
        , allow_trailing_dot: false
      };
  
      validator.isFQDN = function (str, options) {
          options = merge(options, default_fqdn_options);
  
          /* Remove the optional trailing dot before checking validity */
          if (options.allow_trailing_dot && str[str.length - 1] === '.') {
              str = str.substring(0, str.length - 1);
          }
          var parts = str.split('.');
          if (options.require_tld) {
              var tld = parts.pop();
              if (!parts.length || !/^[a-z]{2,}$/i.test(tld)) {
                  return false;
              }
          }
          for (var part, i = 0; i < parts.length; i++) {
              part = parts[i];
              if (options.allow_underscores) {
                  if (part.indexOf('__') >= 0) {
                      return false;
                  }
                  part = part.replace(/_/g, '');
              }
              if (!/^[a-z\u00a1-\uffff0-9-]+$/i.test(part)) {
                  return false;
              }
              if (part[0] === '-' || part[part.length - 1] === '-' ||
                      part.indexOf('---') >= 0) {
                  return false;
              }
          }
          return true;
      };
  
      validator.isAlpha = function (str) {
          return alpha.test(str);
      };
  
      validator.isAlphanumeric = function (str) {
          return alphanumeric.test(str);
      };
  
      validator.isNumeric = function (str) {
          return numeric.test(str);
      };
  
      validator.isHexadecimal = function (str) {
          return hexadecimal.test(str);
      };
  
      validator.isHexColor = function (str) {
          return hexcolor.test(str);
      };
  
      validator.isLowercase = function (str) {
          return str === str.toLowerCase();
      };
  
      validator.isUppercase = function (str) {
          return str === str.toUpperCase();
      };
  
      validator.isInt = function (str) {
          return int.test(str);
      };
  
      validator.isFloat = function (str) {
          return str !== '' && float.test(str);
      };
  
      validator.isDivisibleBy = function (str, num) {
          return validator.toFloat(str) % validator.toInt(num) === 0;
      };
  
      validator.isNull = function (str) {
          return str.length === 0;
      };
  
      validator.isLength = function (str, min, max) {
          var surrogatePairs = str.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g) || [];
          var len = str.length - surrogatePairs.length;
          return len >= min && (typeof max === 'undefined' || len <= max);
      };
  
      validator.isByteLength = function (str, min, max) {
          return str.length >= min && (typeof max === 'undefined' || str.length <= max);
      };
  
      validator.isUUID = function (str, version) {
          var pattern = uuid[version ? version : 'all'];
          return pattern && pattern.test(str);
      };
  
      validator.isDate = function (str) {
          return !isNaN(Date.parse(str));
      };
  
      validator.isAfter = function (str, date) {
          var comparison = validator.toDate(date || new Date())
            , original = validator.toDate(str);
          return !!(original && comparison && original > comparison);
      };
  
      validator.isBefore = function (str, date) {
          var comparison = validator.toDate(date || new Date())
            , original = validator.toDate(str);
          return original && comparison && original < comparison;
      };
  
      validator.isIn = function (str, options) {
          var i;
          if (Object.prototype.toString.call(options) === '[object Array]') {
              var array = [];
              for (i in options) {
                  array[i] = validator.toString(options[i]);
              }
              return array.indexOf(str) >= 0;
          } else if (typeof options === 'object') {
              return options.hasOwnProperty(str);
          } else if (options && typeof options.indexOf === 'function') {
              return options.indexOf(str) >= 0;
          }
          return false;
      };
  
      validator.isCreditCard = function (str) {
          var sanitized = str.replace(/[^0-9]+/g, '');
          if (!creditCard.test(sanitized)) {
              return false;
          }
          var sum = 0, digit, tmpNum, shouldDouble;
          for (var i = sanitized.length - 1; i >= 0; i--) {
              digit = sanitized.substring(i, (i + 1));
              tmpNum = parseInt(digit, 10);
              if (shouldDouble) {
                  tmpNum *= 2;
                  if (tmpNum >= 10) {
                      sum += ((tmpNum % 10) + 1);
                  } else {
                      sum += tmpNum;
                  }
              } else {
                  sum += tmpNum;
              }
              shouldDouble = !shouldDouble;
          }
          return !!((sum % 10) === 0 ? sanitized : false);
      };
  
      validator.isISBN = function (str, version) {
          version = validator.toString(version);
          if (!version) {
              return validator.isISBN(str, 10) || validator.isISBN(str, 13);
          }
          var sanitized = str.replace(/[\s-]+/g, '')
            , checksum = 0, i;
          if (version === '10') {
              if (!isbn10Maybe.test(sanitized)) {
                  return false;
              }
              for (i = 0; i < 9; i++) {
                  checksum += (i + 1) * sanitized.charAt(i);
              }
              if (sanitized.charAt(9) === 'X') {
                  checksum += 10 * 10;
              } else {
                  checksum += 10 * sanitized.charAt(9);
              }
              if ((checksum % 11) === 0) {
                  return !!sanitized;
              }
          } else  if (version === '13') {
              if (!isbn13Maybe.test(sanitized)) {
                  return false;
              }
              var factor = [ 1, 3 ];
              for (i = 0; i < 12; i++) {
                  checksum += factor[i % 2] * sanitized.charAt(i);
              }
              if (sanitized.charAt(12) - ((10 - (checksum % 10)) % 10) === 0) {
                  return !!sanitized;
              }
          }
          return false;
      };
  
      validator.isJSON = function (str) {
          try {
              JSON.parse(str);
          } catch (e) {
              return false;
          }
          return true;
      };
  
      validator.isMultibyte = function (str) {
          return multibyte.test(str);
      };
  
      validator.isAscii = function (str) {
          return ascii.test(str);
      };
  
      validator.isFullWidth = function (str) {
          return fullWidth.test(str);
      };
  
      validator.isHalfWidth = function (str) {
          return halfWidth.test(str);
      };
  
      validator.isVariableWidth = function (str) {
          return fullWidth.test(str) && halfWidth.test(str);
      };
  
      validator.isSurrogatePair = function (str) {
          return surrogatePair.test(str);
      };
  
      validator.isBase64 = function (str) {
          return base64.test(str);
      };
  
      validator.isMongoId = function (str) {
          return validator.isHexadecimal(str) && str.length === 24;
      };
  
      validator.ltrim = function (str, chars) {
          var pattern = chars ? new RegExp('^[' + chars + ']+', 'g') : /^\s+/g;
          return str.replace(pattern, '');
      };
  
      validator.rtrim = function (str, chars) {
          var pattern = chars ? new RegExp('[' + chars + ']+$', 'g') : /\s+$/g;
          return str.replace(pattern, '');
      };
  
      validator.trim = function (str, chars) {
          var pattern = chars ? new RegExp('^[' + chars + ']+|[' + chars + ']+$', 'g') : /^\s+|\s+$/g;
          return str.replace(pattern, '');
      };
  
      validator.escape = function (str) {
          return (str.replace(/&/g, '&amp;')
              .replace(/"/g, '&quot;')
              .replace(/'/g, '&#x27;')
              .replace(/</g, '&lt;')
              .replace(/>/g, '&gt;')
              .replace(/\//g, '&#x2F;'));
      };
  
      validator.stripLow = function (str, keep_new_lines) {
          var chars = keep_new_lines ? '\x00-\x09\x0B\x0C\x0E-\x1F\x7F' : '\x00-\x1F\x7F';
          return validator.blacklist(str, chars);
      };
  
      validator.whitelist = function (str, chars) {
          return str.replace(new RegExp('[^' + chars + ']+', 'g'), '');
      };
  
      validator.blacklist = function (str, chars) {
          return str.replace(new RegExp('[' + chars + ']+', 'g'), '');
      };
  
      var default_normalize_email_options = {
          lowercase: true
      };
  
      validator.normalizeEmail = function (email, options) {
          options = merge(options, default_normalize_email_options);
          if (!validator.isEmail(email)) {
              return false;
          }
          var parts = email.split('@', 2);
          parts[1] = parts[1].toLowerCase();
          if (options.lowercase) {
              parts[0] = parts[0].toLowerCase();
          }
          if (parts[1] === 'gmail.com' || parts[1] === 'googlemail.com') {
              if (!options.lowercase) {
                  parts[0] = parts[0].toLowerCase();
              }
              parts[0] = parts[0].replace(/\./g, '').split('+')[0];
              parts[1] = 'gmail.com';
          }
          return parts.join('@');
      };
  
      function merge(obj, defaults) {
          obj = obj || {};
          for (var key in defaults) {
              if (typeof obj[key] === 'undefined') {
                  obj[key] = defaults[key];
              }
          }
          return obj;
      }
  
      validator.init();
  
      return validator;
  
  });
  