From 7d7afdc6d6aa56dd12578d925974eab0f88964ea Mon Sep 17 00:00:00 2001 From: Peter Dave Hello Date: Sun, 18 Sep 2016 00:11:53 +0800 Subject: [PATCH] add h5Validate v0.9.0, close #3481 --- .../h5Validate/0.9.0/jquery.h5validate.js | 553 ++++++++++++++++++ .../h5Validate/0.9.0/jquery.h5validate.min.js | 2 + .../0.9.0/jquery.h5validate.min.js.map | 1 + ajax/libs/h5Validate/package.json | 2 +- 4 files changed, 557 insertions(+), 1 deletion(-) create mode 100644 ajax/libs/h5Validate/0.9.0/jquery.h5validate.js create mode 100644 ajax/libs/h5Validate/0.9.0/jquery.h5validate.min.js create mode 100644 ajax/libs/h5Validate/0.9.0/jquery.h5validate.min.js.map diff --git a/ajax/libs/h5Validate/0.9.0/jquery.h5validate.js b/ajax/libs/h5Validate/0.9.0/jquery.h5validate.js new file mode 100644 index 00000000000000..204ee13509055e --- /dev/null +++ b/ajax/libs/h5Validate/0.9.0/jquery.h5validate.js @@ -0,0 +1,553 @@ +/** + * h5Validate + * @version v0.9.0 + * Using semantic versioning: http://semver.org/ + * @author Eric Hamilton http://ericleads.com/ + * @copyright 2010 - 2012 Eric Hamilton + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + * + * Developed under the sponsorship of RootMusic, Zumba Fitness, LLC, and Rese Property Management + */ + +/*global jQuery, window, console */ +(function ($) { + 'use strict'; + var console = window.console || function () {}, + h5 = { // Public API + defaults : { + debug: false, + + RODom: false, + + // HTML5-compatible validation pattern library that can be extended and/or overriden. + patternLibrary : { //** TODO: Test the new regex patterns. Should I apply these to the new input types? + // **TODO: password + phone: /([\+][0-9]{1,3}([ \.\-])?)?([\(]{1}[0-9]{3}[\)])?([0-9A-Z \.\-]{1,32})((x|ext|extension)?[0-9]{1,4}?)/, + + // Shamelessly lifted from Scott Gonzalez via the Bassistance Validation plugin http://projects.scottsplayground.com/email_address_validation/ + email: /((([a-zA-Z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-zA-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-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?/, + + // Shamelessly lifted from Scott Gonzalez via the Bassistance Validation plugin http://projects.scottsplayground.com/iri/ + url: /(https?|ftp):\/\/(((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?/, + + // Number, including positive, negative, and floating decimal. Credit: bassistance + number: /-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?/, + + // Date in ISO format. Credit: bassistance + dateISO: /\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}/, + + alpha: /[a-zA-Z]+/, + alphaNumeric: /\w+/, + integer: /-?\d+/ + }, + + // The prefix to use for dynamically-created class names. + classPrefix: 'h5-', + + errorClass: 'ui-state-error', // No prefix for these. + validClass: 'ui-state-valid', // " + activeClass: 'active', // Prefix will get prepended. + requiredClass: 'required', + requiredAttribute: 'required', + patternAttribute: 'pattern', + + // Attribute which stores the ID of the error container element (without the hash). + errorAttribute: 'data-h5-errorid', + + // Events API + customEvents: { + 'validate': true + }, + + // Setup KB event delegation. + kbSelectors: ':input:not(:button):not(:disabled):not(.novalidate)', + focusout: true, + focusin: false, + change: true, + keyup: false, + activeKeyup: true, + + // Setup mouse event delegation. + mSelectors: '[type="range"]:not(:disabled):not(.novalidate), :radio:not(:disabled):not(.novalidate), :checkbox:not(:disabled):not(.novalidate), select:not(:disabled):not(.novalidate), option:not(:disabled):not(.novalidate)', + click: true, + + // What do we name the required .data variable? + requiredVar: 'h5-required', + + // What do we name the pattern .data variable? + patternVar: 'h5-pattern', + stripMarkup: true, + + // Run submit related checks and prevent form submission if any fields are invalid? + submit: true, + + // Move focus to the first invalid field on submit? + focusFirstInvalidElementOnSubmit: true, + + // When submitting, validate elements that haven't been validated yet? + validateOnSubmit: true, + + // Callback stubs + invalidCallback: function () {}, + validCallback: function () {}, + + // Elements to validate with allValid (only validating visible elements) + allValidSelectors: ':input:visible:not(:button):not(:disabled):not(.novalidate)', + + // Mark field invalid. + // ** TODO: Highlight labels + // ** TODO: Implement setCustomValidity as per the spec: + // http://www.whatwg.org/specs/web-apps/current-work/multipage/association-of-controls-and-forms.html#dom-cva-setcustomvalidity + markInvalid: function markInvalid(options) { + var $element = $(options.element), + $errorID = $(options.errorID); + $element.addClass(options.errorClass).removeClass(options.validClass); + + // User needs help. Enable active validation. + $element.addClass(options.settings.activeClass); + + if ($errorID.length) { // These ifs are technically not needed, but improve server-side performance + if ($element.attr('title')) { + $errorID.text($element.attr('title')); + } + $errorID.show(); + } + $element.data('valid', false); + options.settings.invalidCallback.call(options.element, options.validity); + return $element; + }, + + // Mark field valid. + markValid: function markValid(options) { + var $element = $(options.element), + $errorID = $(options.errorID); + + $element.addClass(options.validClass).removeClass(options.errorClass); + if ($errorID.length) { + $errorID.hide(); + } + $element.data('valid', true); + options.settings.validCallback.call(options.element, options.validity); + return $element; + }, + + // Unmark field + unmark: function unmark(options) { + var $element = $(options.element); + $element.removeClass(options.errorClass).removeClass(options.validClass); + $element.form.find("#" + options.element.id).removeClass(options.errorClass).removeClass(options.validClass); + return $element; + } + } + }, + + // Aliases + defaults = h5.defaults, + patternLibrary = defaults.patternLibrary, + + createValidity = function createValidity(validity) { + return $.extend({ + customError: validity.customError || false, + patternMismatch: validity.patternMismatch || false, + rangeOverflow: validity.rangeOverflow || false, + rangeUnderflow: validity.rangeUnderflow || false, + stepMismatch: validity.stepMismatch || false, + tooLong: validity.tooLong || false, + typeMismatch: validity.typeMismatch || false, + valid: validity.valid || true, + valueMissing: validity.valueMissing || false + }, validity); + }, + + methods = { + /** + * Check the validity of the current field + * @param {object} settings instance settings + * @param {object} options + * .revalidate - trigger validation function first? + * @return {Boolean} + */ + isValid: function (settings, options) { + var $this = $(this); + + options = (settings && options) || {}; + + // Revalidate defaults to true + if (options.revalidate !== false) { + $this.trigger('validate'); + } + + return $this.data('valid'); // get the validation result + }, + allValid: function (config, options) { + var valid = true, + formValidity = [], + $this = $(this), + $allFields, + $filteredFields, + radioNames = [], + getValidity = function getValidity(e, data) { + data.e = e; + formValidity.push(data); + }, + settings = $.extend({}, config, options); // allow options to override settings + + options = options || {}; + + $this.trigger('formValidate', {settings: $.extend(true, {}, settings)}); + + // Make sure we're not triggering handlers more than we need to. + $this.undelegate(settings.allValidSelectors, + '.allValid', getValidity); + $this.delegate(settings.allValidSelectors, + 'validated.allValid', getValidity); + + $allFields = $this.find(settings.allValidSelectors); + + // Filter radio buttons with the same name and keep only one, + // since they will be checked as a group by isValid() + $filteredFields = $allFields.filter(function(index) { + var name; + + if(this.tagName === "INPUT" + && this.type === "radio") { + name = this.name; + if(radioNames[name] === true) { + return false; + } + radioNames[name] = true; + } + return true; + }); + + $filteredFields.each(function () { + var $this = $(this); + valid = $this.h5Validate('isValid', options) && valid; + }); + + $this.trigger('formValidated', {valid: valid, elements: formValidity}); + return valid; + }, + validate: function (settings) { + // Get the HTML5 pattern attribute if it exists. + // ** TODO: If a pattern class exists, grab the pattern from the patternLibrary, but the pattern attrib should override that value. + var $this = $(this), + pattern = $this.filter('[pattern]')[0] ? $this.attr('pattern') : false, + + // The pattern attribute must match the whole value, not just a subset: + // "...as if it implied a ^(?: at the start of the pattern and a )$ at the end." + re = new RegExp('^(?:' + pattern + ')$'), + $radiosWithSameName = null, + value = ($this.is('[type=checkbox]')) ? + $this.is(':checked') : ($this.is('[type=radio]') ? + // Cache all radio buttons (in the same form) with the same name as this one + ($radiosWithSameName = $this.parents('form') + // **TODO: escape the radio buttons' name before using it in the jQuery selector + .find('input[name="' + $this.attr('name') + '"]')) + .filter(':checked') + .length > 0 : $this.val()), + errorClass = settings.errorClass, + validClass = settings.validClass, + errorIDbare = $this.attr(settings.errorAttribute) || false, // Get the ID of the error element. + errorID = errorIDbare ? '#' + errorIDbare.replace(/(:|\.|\[|\])/g,'\\$1') : false, // Add the hash for convenience. This is done in two steps to avoid two attribute lookups. + required = false, + validity = createValidity({element: this, valid: true}), + $checkRequired = $(''), + maxlength; + + /* If the required attribute exists, set it required to true, unless it's set 'false'. + * This is a minor deviation from the spec, but it seems some browsers have falsey + * required values if the attribute is empty (should be true). The more conformant + * version of this failed sanity checking in the browser environment. + * This plugin is meant to be practical, not ideologically married to the spec. + */ + // Feature fork + if ($checkRequired.filter('[required]') && $checkRequired.filter('[required]').length) { + required = ($this.filter('[required]').length && $this.attr('required') !== 'false'); + } else { + required = ($this.attr('required') !== undefined); + } + + if (settings.debug && window.console) { + console.log('Validate called on "' + value + '" with regex "' + re + '". Required: ' + required); // **DEBUG + console.log('Regex test: ' + re.test(value) + ', Pattern: ' + pattern); // **DEBUG + } + + maxlength = parseInt($this.attr('maxlength'), 10); + if (!isNaN(maxlength) && value.length > maxlength) { + validity.valid = false; + validity.tooLong = true; + } + + if (required && !value) { + validity.valid = false; + validity.valueMissing = true; + } else if (pattern && !re.test(value) && value) { + validity.valid = false; + validity.patternMismatch = true; + } else { + if (!settings.RODom) { + settings.markValid({ + element: this, + validity: validity, + errorClass: errorClass, + validClass: validClass, + errorID: errorID, + settings: settings + }); + } + } + + if (!validity.valid) { + if (!settings.RODom) { + settings.markInvalid({ + element: this, + validity: validity, + errorClass: errorClass, + validClass: validClass, + errorID: errorID, + settings: settings + }); + } + } + $this.trigger('validated', validity); + + // If it's a radio button, also validate the other radio buttons with the same name + // (while making sure the call is not recursive) + if($radiosWithSameName !== null + && settings.alreadyCheckingRelatedRadioButtons !== true) { + + settings.alreadyCheckingRelatedRadioButtons = true; + + $radiosWithSameName + .not($this) + .trigger('validate'); + + settings.alreadyCheckingRelatedRadioButtons = false; + + } + }, + + /** + * Take the event preferences and delegate the events to selected + * objects. + * + * @param {object} eventFlags The object containing event flags. + * + * @returns {element} The passed element (for method chaining). + */ + delegateEvents: function (selectors, eventFlags, element, settings) { + var events = {}, + key = 0, + validate = function () { + settings.validate.call(this, settings); + }; + $.each(eventFlags, function (key, value) { + if (value) { + events[key] = key; + } + }); + // key = 0; + for (key in events) { + if (events.hasOwnProperty(key)) { + $(element).delegate(selectors, events[key] + '.h5Validate', validate); + } + } + return element; + }, + /** + * Prepare for event delegation. + * + * @param {object} settings The full plugin state, including + * options. + * + * @returns {object} jQuery object for chaining. + */ + bindDelegation: function (settings) { + var $this = $(this), + $forms; + // Attach patterns from the library to elements. + // **TODO: pattern / validation method matching should + // take place inside the validate action. + $.each(patternLibrary, function (key, value) { + var pattern = value.toString(); + pattern = pattern.substring(1, pattern.length - 1); + $('.' + settings.classPrefix + key).attr('pattern', pattern); + }); + + $forms = $this.filter('form') + .add($this.find('form')) + .add($this.parents('form')); + + $forms + .attr('novalidate', 'novalidate') + .submit(checkValidityOnSubmitHandler); + + $forms.find("input[formnovalidate][type='submit']").click(function(){ + $(this).closest("form").unbind('submit', checkValidityOnSubmitHandler); + }); + + return this.each(function () { + var kbEvents = { + focusout: settings.focusout, + focusin: settings.focusin, + change: settings.change, + keyup: settings.keyup + }, + mEvents = { + click: settings.click + }, + activeEvents = { + keyup: settings.activeKeyup + }; + + settings.delegateEvents(':input', settings.customEvents, this, settings); + settings.delegateEvents(settings.kbSelectors, kbEvents, this, settings); + settings.delegateEvents(settings.mSelectors, mEvents, this, settings); + settings.delegateEvents(settings.activeClassSelector, activeEvents, this, settings); + settings.delegateEvents('textarea[maxlength]', {keyup: true}, this, settings); + }); + } + }, + + /** + * Event handler for the form submit event. + * When settings.submit is enabled: + * - prevents submission if any invalid fields are found. + * - Optionally validates all fields. + * - Optionally moves focus to the first invalid field. + * + * @param {object} evt The jQuery Event object as from the submit event. + * + * @returns {object} undefined if no validation was done, true if validation passed, false if validation didn't. + */ + checkValidityOnSubmitHandler = function(evt) { + + var $this, + settings = getInstance.call(this), + allValid; + + if(settings.submit !== true) { + return; + } + + $this = $(this); + allValid = $this.h5Validate('allValid', { revalidate: settings.validateOnSubmit === true }); + + if(allValid !== true) { + evt.preventDefault(); + + if(settings.focusFirstInvalidElementOnSubmit === true){ + var $invalid = $(settings.allValidSelectors, $this) + .filter(function(index){ + return $(this).h5Validate('isValid', { revalidate: false }) !== true; + }); + + $invalid.first().focus(); + } + } + + return allValid; + }, + + instances = [], + + buildSettings = function buildSettings(options) { + // Combine defaults and options to get current settings. + var settings = $.extend({}, defaults, options, methods), + activeClass = settings.classPrefix + settings.activeClass; + + return $.extend(settings, { + activeClass: activeClass, + activeClassSelector: '.' + activeClass, + requiredClass: settings.classPrefix + settings.requiredClass, + el: this + }); + }, + + getInstance = function getInstance() { + var $parent = $(this).closest('[data-h5-instanceId]'); + return instances[$parent.attr('data-h5-instanceId')]; + }, + + setInstance = function setInstance(settings) { + var instanceId = instances.push(settings) - 1; + if (settings.RODom !== true) { + $(this).attr('data-h5-instanceId', instanceId); + } + $(this).trigger('instance', { 'data-h5-instanceId': instanceId }); + }; + + $.h5Validate = { + /** + * Take a map of pattern names and HTML5-compatible regular + * expressions, and add them to the patternLibrary. Patterns in + * the library are automatically assigned to HTML element pattern + * attributes for validation. + * + * @param {Object} patterns A map of pattern names and HTML5 compatible + * regular expressions. + * + * @returns {Object} patternLibrary The modified pattern library + */ + addPatterns: function (patterns) { + var patternLibrary = defaults.patternLibrary, + key; + for (key in patterns) { + if (patterns.hasOwnProperty(key)) { + patternLibrary[key] = patterns[key]; + } + } + return patternLibrary; + }, + /** + * Take a valid jQuery selector, and a list of valid values to + * validate against. + * If the user input isn't in the list, validation fails. + * + * @param {String} selector Any valid jQuery selector. + * + * @param {Array} values A list of valid values to validate selected + * fields against. + */ + validValues: function (selector, values) { + var i = 0, + ln = values.length, + pattern = '', + re; + // Build regex pattern + for (i = 0; i < ln; i += 1) { + pattern = pattern ? pattern + '|' + values[i] : values[i]; + } + re = new RegExp('^(?:' + pattern + ')$'); + $(selector).data('regex', re); + } + }; + + $.fn.h5Validate = function h5Validate(options) { + var action, + args, + settings; + + if (typeof options === 'string' && typeof methods[options] === 'function') { + // Whoah, hold on there! First we need to get the instance: + settings = getInstance.call(this); + + args = [].slice.call(arguments, 0); + action = options; + args.shift(); + args = $.merge([settings], args); + + // Use settings here so we can plug methods into the instance dynamically? + return settings[action].apply(this, args); + } + + settings = buildSettings.call(this, options); + setInstance.call(this, settings); + + // Returning the jQuery object allows for method chaining. + return methods.bindDelegation.call(this, settings); + }; +}(jQuery)); diff --git a/ajax/libs/h5Validate/0.9.0/jquery.h5validate.min.js b/ajax/libs/h5Validate/0.9.0/jquery.h5validate.min.js new file mode 100644 index 00000000000000..a9980476fb708f --- /dev/null +++ b/ajax/libs/h5Validate/0.9.0/jquery.h5validate.min.js @@ -0,0 +1,2 @@ +!function(e){"use strict";var t=window.console||function(){},a={defaults:{debug:!1,RODom:!1,patternLibrary:{phone:/([\+][0-9]{1,3}([ \.\-])?)?([\(]{1}[0-9]{3}[\)])?([0-9A-Z \.\-]{1,32})((x|ext|extension)?[0-9]{1,4}?)/,email:/((([a-zA-Z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-zA-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-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?/,url:/(https?|ftp):\/\/(((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?/,number:/-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?/,dateISO:/\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}/,alpha:/[a-zA-Z]+/,alphaNumeric:/\w+/,integer:/-?\d+/},classPrefix:"h5-",errorClass:"ui-state-error",validClass:"ui-state-valid",activeClass:"active",requiredClass:"required",requiredAttribute:"required",patternAttribute:"pattern",errorAttribute:"data-h5-errorid",customEvents:{validate:!0},kbSelectors:":input:not(:button):not(:disabled):not(.novalidate)",focusout:!0,focusin:!1,change:!0,keyup:!1,activeKeyup:!0,mSelectors:'[type="range"]:not(:disabled):not(.novalidate), :radio:not(:disabled):not(.novalidate), :checkbox:not(:disabled):not(.novalidate), select:not(:disabled):not(.novalidate), option:not(:disabled):not(.novalidate)',click:!0,requiredVar:"h5-required",patternVar:"h5-pattern",stripMarkup:!0,submit:!0,focusFirstInvalidElementOnSubmit:!0,validateOnSubmit:!0,invalidCallback:function(){},validCallback:function(){},allValidSelectors:":input:visible:not(:button):not(:disabled):not(.novalidate)",markInvalid:function(t){var a=e(t.element),i=e(t.errorID);return a.addClass(t.errorClass).removeClass(t.validClass),a.addClass(t.settings.activeClass),i.length&&(a.attr("title")&&i.text(a.attr("title")),i.show()),a.data("valid",!1),t.settings.invalidCallback.call(t.element,t.validity),a},markValid:function(t){var a=e(t.element),i=e(t.errorID);return a.addClass(t.validClass).removeClass(t.errorClass),i.length&&i.hide(),a.data("valid",!0),t.settings.validCallback.call(t.element,t.validity),a},unmark:function(t){var a=e(t.element);return a.removeClass(t.errorClass).removeClass(t.validClass),a.form.find("#"+t.element.id).removeClass(t.errorClass).removeClass(t.validClass),a}}},i=a.defaults,u=i.patternLibrary,r=function(t){return e.extend({customError:t.customError||!1,patternMismatch:t.patternMismatch||!1,rangeOverflow:t.rangeOverflow||!1,rangeUnderflow:t.rangeUnderflow||!1,stepMismatch:t.stepMismatch||!1,tooLong:t.tooLong||!1,typeMismatch:t.typeMismatch||!1,valid:t.valid||!0,valueMissing:t.valueMissing||!1},t)},l={isValid:function(t,a){var i=e(this);return a=t&&a||{},a.revalidate!==!1&&i.trigger("validate"),i.data("valid")},allValid:function(t,a){var i,u,r=!0,l=[],n=e(this),F=[],d=function(e,t){t.e=e,l.push(t)},s=e.extend({},t,a);return a=a||{},n.trigger("formValidate",{settings:e.extend(!0,{},s)}),n.undelegate(s.allValidSelectors,".allValid",d),n.delegate(s.allValidSelectors,"validated.allValid",d),i=n.find(s.allValidSelectors),u=i.filter(function(e){var t;if("INPUT"===this.tagName&&"radio"===this.type){if(t=this.name,F[t]===!0)return!1;F[t]=!0}return!0}),u.each(function(){var t=e(this);r=t.h5Validate("isValid",a)&&r}),n.trigger("formValidated",{valid:r,elements:l}),r},validate:function(a){var i,u=e(this),l=!!u.filter("[pattern]")[0]&&u.attr("pattern"),n=new RegExp("^(?:"+l+")$"),F=null,d=u.is("[type=checkbox]")?u.is(":checked"):u.is("[type=radio]")?(F=u.parents("form").find('input[name="'+u.attr("name")+'"]')).filter(":checked").length>0:u.val(),s=a.errorClass,o=a.validClass,c=u.attr(a.errorAttribute)||!1,v=!!c&&"#"+c.replace(/(:|\.|\[|\])/g,"\\$1"),f=!1,h=r({element:this,valid:!0}),D=e("");f=D.filter("[required]")&&D.filter("[required]").length?u.filter("[required]").length&&"false"!==u.attr("required"):void 0!==u.attr("required"),a.debug&&window.console&&(t.log('Validate called on "'+d+'" with regex "'+n+'". Required: '+f),t.log("Regex test: "+n.test(d)+", Pattern: "+l)),i=parseInt(u.attr("maxlength"),10),!isNaN(i)&&d.length>i&&(h.valid=!1,h.tooLong=!0),f&&!d?(h.valid=!1,h.valueMissing=!0):l&&!n.test(d)&&d?(h.valid=!1,h.patternMismatch=!0):a.RODom||a.markValid({element:this,validity:h,errorClass:s,validClass:o,errorID:v,settings:a}),h.valid||a.RODom||a.markInvalid({element:this,validity:h,errorClass:s,validClass:o,errorID:v,settings:a}),u.trigger("validated",h),null!==F&&a.alreadyCheckingRelatedRadioButtons!==!0&&(a.alreadyCheckingRelatedRadioButtons=!0,F.not(u).trigger("validate"),a.alreadyCheckingRelatedRadioButtons=!1)},delegateEvents:function(t,a,i,u){var r={},l=0,n=function(){u.validate.call(this,u)};e.each(a,function(e,t){t&&(r[e]=e)});for(l in r)r.hasOwnProperty(l)&&e(i).delegate(t,r[l]+".h5Validate",n);return i},bindDelegation:function(t){var a,i=e(this);return e.each(u,function(a,i){var u=i.toString();u=u.substring(1,u.length-1),e("."+t.classPrefix+a).attr("pattern",u)}),a=i.filter("form").add(i.find("form")).add(i.parents("form")),a.attr("novalidate","novalidate").submit(n),a.find("input[formnovalidate][type='submit']").click(function(){e(this).closest("form").unbind("submit",n)}),this.each(function(){var e={focusout:t.focusout,focusin:t.focusin,change:t.change,keyup:t.keyup},a={click:t.click},i={keyup:t.activeKeyup};t.delegateEvents(":input",t.customEvents,this,t),t.delegateEvents(t.kbSelectors,e,this,t),t.delegateEvents(t.mSelectors,a,this,t),t.delegateEvents(t.activeClassSelector,i,this,t),t.delegateEvents("textarea[maxlength]",{keyup:!0},this,t)})}},n=function(t){var a,i,u=s.call(this);if(u.submit===!0){if(a=e(this),i=a.h5Validate("allValid",{revalidate:u.validateOnSubmit===!0}),i!==!0&&(t.preventDefault(),u.focusFirstInvalidElementOnSubmit===!0)){var r=e(u.allValidSelectors,a).filter(function(t){return e(this).h5Validate("isValid",{revalidate:!1})!==!0});r.first().focus()}return i}},F=[],d=function(t){var a=e.extend({},i,t,l),u=a.classPrefix+a.activeClass;return e.extend(a,{activeClass:u,activeClassSelector:"."+u,requiredClass:a.classPrefix+a.requiredClass,el:this})},s=function(){var t=e(this).closest("[data-h5-instanceId]");return F[t.attr("data-h5-instanceId")]},o=function(t){var a=F.push(t)-1;t.RODom!==!0&&e(this).attr("data-h5-instanceId",a),e(this).trigger("instance",{"data-h5-instanceId":a})};e.h5Validate={addPatterns:function(e){var t,a=i.patternLibrary;for(t in e)e.hasOwnProperty(t)&&(a[t]=e[t]);return a},validValues:function(t,a){var i,u=0,r=a.length,l="";for(u=0;u