home *** CD-ROM | disk | FTP | other *** search
/ 61.19.244.139 / 61.19.244.139.zip / 61.19.244.139 / wsCompulTransfer / cp2013 / Scripts / jquery.validate.unobtrusive.js < prev    next >
Text File  |  2013-06-07  |  16KB  |  367 lines

  1. /*!
  2. ** Unobtrusive validation support library for jQuery and jQuery Validate
  3. ** Copyright (C) Microsoft Corporation. All rights reserved.
  4. */
  5.  
  6. /*jslint white: true, browser: true, onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: false */
  7. /*global document: false, jQuery: false */
  8.  
  9. (function ($) {
  10.     var $jQval = $.validator,
  11.         adapters,
  12.         data_validation = "unobtrusiveValidation";
  13.  
  14.     function setValidationValues(options, ruleName, value) {
  15.         options.rules[ruleName] = value;
  16.         if (options.message) {
  17.             options.messages[ruleName] = options.message;
  18.         }
  19.     }
  20.  
  21.     function splitAndTrim(value) {
  22.         return value.replace(/^\s+|\s+$/g, "").split(/\s*,\s*/g);
  23.     }
  24.  
  25.     function escapeAttributeValue(value) {
  26.         // As mentioned on http://api.jquery.com/category/selectors/
  27.         return value.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g, "\\$1");
  28.     }
  29.  
  30.     function getModelPrefix(fieldName) {
  31.         return fieldName.substr(0, fieldName.lastIndexOf(".") + 1);
  32.     }
  33.  
  34.     function appendModelPrefix(value, prefix) {
  35.         if (value.indexOf("*.") === 0) {
  36.             value = value.replace("*.", prefix);
  37.         }
  38.         return value;
  39.     }
  40.  
  41.     function onError(error, inputElement) {  // 'this' is the form element
  42.         var container = $(this).find("[data-valmsg-for='" + escapeAttributeValue(inputElement[0].name) + "']"),
  43.             replaceAttrValue = container.attr("data-valmsg-replace"),
  44.             replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) !== false : null;
  45.  
  46.         container.removeClass("field-validation-valid").addClass("field-validation-error");
  47.         error.data("unobtrusiveContainer", container);
  48.  
  49.         if (replace) {
  50.             container.empty();
  51.             error.removeClass("input-validation-error").appendTo(container);
  52.         }
  53.         else {
  54.             error.hide();
  55.         }
  56.     }
  57.  
  58.     function onErrors(event, validator) {  // 'this' is the form element
  59.         var container = $(this).find("[data-valmsg-summary=true]"),
  60.             list = container.find("ul");
  61.  
  62.         if (list && list.length && validator.errorList.length) {
  63.             list.empty();
  64.             container.addClass("validation-summary-errors").removeClass("validation-summary-valid");
  65.  
  66.             $.each(validator.errorList, function () {
  67.                 $("<li />").html(this.message).appendTo(list);
  68.             });
  69.         }
  70.     }
  71.  
  72.     function onSuccess(error) {  // 'this' is the form element
  73.         var container = error.data("unobtrusiveContainer"),
  74.             replaceAttrValue = container.attr("data-valmsg-replace"),
  75.             replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) : null;
  76.  
  77.         if (container) {
  78.             container.addClass("field-validation-valid").removeClass("field-validation-error");
  79.             error.removeData("unobtrusiveContainer");
  80.  
  81.             if (replace) {
  82.                 container.empty();
  83.             }
  84.         }
  85.     }
  86.  
  87.     function onReset(event) {  // 'this' is the form element
  88.         var $form = $(this);
  89.         $form.data("validator").resetForm();
  90.         $form.find(".validation-summary-errors")
  91.             .addClass("validation-summary-valid")
  92.             .removeClass("validation-summary-errors");
  93.         $form.find(".field-validation-error")
  94.             .addClass("field-validation-valid")
  95.             .removeClass("field-validation-error")
  96.             .removeData("unobtrusiveContainer")
  97.             .find(">*")  // If we were using valmsg-replace, get the underlying error
  98.                 .removeData("unobtrusiveContainer");
  99.     }
  100.  
  101.     function validationInfo(form) {
  102.         var $form = $(form),
  103.             result = $form.data(data_validation),
  104.             onResetProxy = $.proxy(onReset, form);
  105.  
  106.         if (!result) {
  107.             result = {
  108.                 options: {  // options structure passed to jQuery Validate's validate() method
  109.                     errorClass: "input-validation-error",
  110.                     errorElement: "span",
  111.                     errorPlacement: $.proxy(onError, form),
  112.                     invalidHandler: $.proxy(onErrors, form),
  113.                     messages: {},
  114.                     rules: {},
  115.                     success: $.proxy(onSuccess, form)
  116.                 },
  117.                 attachValidation: function () {
  118.                     $form
  119.                         .unbind("reset." + data_validation, onResetProxy)
  120.                         .bind("reset." + data_validation, onResetProxy)
  121.                         .validate(this.options);
  122.                 },
  123.                 validate: function () {  // a validation function that is called by unobtrusive Ajax
  124.                     $form.validate();
  125.                     return $form.valid();
  126.                 }
  127.             };
  128.             $form.data(data_validation, result);
  129.         }
  130.  
  131.         return result;
  132.     }
  133.  
  134.     $jQval.unobtrusive = {
  135.         adapters: [],
  136.  
  137.         parseElement: function (element, skipAttach) {
  138.             /// <summary>
  139.             /// Parses a single HTML element for unobtrusive validation attributes.
  140.             /// </summary>
  141.             /// <param name="element" domElement="true">The HTML element to be parsed.</param>
  142.             /// <param name="skipAttach" type="Boolean">[Optional] true to skip attaching the
  143.             /// validation to the form. If parsing just this single element, you should specify true.
  144.             /// If parsing several elements, you should specify false, and manually attach the validation
  145.             /// to the form when you are finished. The default is false.</param>
  146.             var $element = $(element),
  147.                 form = $element.parents("form")[0],
  148.                 valInfo, rules, messages;
  149.  
  150.             if (!form) {  // Cannot do client-side validation without a form
  151.                 return;
  152.             }
  153.  
  154.             valInfo = validationInfo(form);
  155.             valInfo.options.rules[element.name] = rules = {};
  156.             valInfo.options.messages[element.name] = messages = {};
  157.  
  158.             $.each(this.adapters, function () {
  159.                 var prefix = "data-val-" + this.name,
  160.                     message = $element.attr(prefix),
  161.                     paramValues = {};
  162.  
  163.                 if (message !== undefined) {  // Compare against undefined, because an empty message is legal (and falsy)
  164.                     prefix += "-";
  165.  
  166.                     $.each(this.params, function () {
  167.                         paramValues[this] = $element.attr(prefix + this);
  168.                     });
  169.  
  170.                     this.adapt({
  171.                         element: element,
  172.                         form: form,
  173.                         message: message,
  174.                         params: paramValues,
  175.                         rules: rules,
  176.                         messages: messages
  177.                     });
  178.                 }
  179.             });
  180.  
  181.             $.extend(rules, { "__dummy__": true });
  182.  
  183.             if (!skipAttach) {
  184.                 valInfo.attachValidation();
  185.             }
  186.         },
  187.  
  188.         parse: function (selector) {
  189.             /// <summary>
  190.             /// Parses all the HTML elements in the specified selector. It looks for input elements decorated
  191.             /// with the [data-val=true] attribute value and enables validation according to the data-val-*
  192.             /// attribute values.
  193.             /// </summary>
  194.             /// <param name="selector" type="String">Any valid jQuery selector.</param>
  195.             var $forms = $(selector)
  196.                 .parents("form")
  197.                 .andSelf()
  198.                 .add($(selector).find("form"))
  199.                 .filter("form");
  200.  
  201.             $(selector).find(":input[data-val=true]").each(function () {
  202.                 $jQval.unobtrusive.parseElement(this, true);
  203.             });
  204.  
  205.             $forms.each(function () {
  206.                 var info = validationInfo(this);
  207.                 if (info) {
  208.                     info.attachValidation();
  209.                 }
  210.             });
  211.         }
  212.     };
  213.  
  214.     adapters = $jQval.unobtrusive.adapters;
  215.  
  216.     adapters.add = function (adapterName, params, fn) {
  217.         /// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation.</summary>
  218.         /// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
  219.         /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).</param>
  220.         /// <param name="params" type="Array" optional="true">[Optional] An array of parameter names (strings) that will
  221.         /// be extracted from the data-val-nnnn-mmmm HTML attributes (where nnnn is the adapter name, and
  222.         /// mmmm is the parameter name).</param>
  223.         /// <param name="fn" type="Function">The function to call, which adapts the values from the HTML
  224.         /// attributes into jQuery Validate rules and/or messages.</param>
  225.         /// <returns type="jQuery.validator.unobtrusive.adapters" />
  226.         if (!fn) {  // Called with no params, just a function
  227.             fn = params;
  228.             params = [];
  229.         }
  230.         this.push({ name: adapterName, params: params, adapt: fn });
  231.         return this;
  232.     };
  233.  
  234.     adapters.addBool = function (adapterName, ruleName) {
  235.         /// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where
  236.         /// the jQuery Validate validation rule has no parameter values.</summary>
  237.         /// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
  238.         /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).</param>
  239.         /// <param name="ruleName" type="String" optional="true">[Optional] The name of the jQuery Validate rule. If not provided, the value
  240.         /// of adapterName will be used instead.</param>
  241.         /// <returns type="jQuery.validator.unobtrusive.adapters" />
  242.         return this.add(adapterName, function (options) {
  243.             setValidationValues(options, ruleName || adapterName, true);
  244.         });
  245.     };
  246.  
  247.     adapters.addMinMax = function (adapterName, minRuleName, maxRuleName, minMaxRuleName, minAttribute, maxAttribute) {
  248.         /// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where
  249.         /// the jQuery Validate validation has three potential rules (one for min-only, one for max-only, and
  250.         /// one for min-and-max). The HTML parameters are expected to be named -min and -max.</summary>
  251.         /// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
  252.         /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).</param>
  253.         /// <param name="minRuleName" type="String">The name of the jQuery Validate rule to be used when you only
  254.         /// have a minimum value.</param>
  255.         /// <param name="maxRuleName" type="String">The name of the jQuery Validate rule to be used when you only
  256.         /// have a maximum value.</param>
  257.         /// <param name="minMaxRuleName" type="String">The name of the jQuery Validate rule to be used when you
  258.         /// have both a minimum and maximum value.</param>
  259.         /// <param name="minAttribute" type="String" optional="true">[Optional] The name of the HTML attribute that
  260.         /// contains the minimum value. The default is "min".</param>
  261.         /// <param name="maxAttribute" type="String" optional="true">[Optional] The name of the HTML attribute that
  262.         /// contains the maximum value. The default is "max".</param>
  263.         /// <returns type="jQuery.validator.unobtrusive.adapters" />
  264.         return this.add(adapterName, [minAttribute || "min", maxAttribute || "max"], function (options) {
  265.             var min = options.params.min,
  266.                 max = options.params.max;
  267.  
  268.             if (min && max) {
  269.                 setValidationValues(options, minMaxRuleName, [min, max]);
  270.             }
  271.             else if (min) {
  272.                 setValidationValues(options, minRuleName, min);
  273.             }
  274.             else if (max) {
  275.                 setValidationValues(options, maxRuleName, max);
  276.             }
  277.         });
  278.     };
  279.  
  280.     adapters.addSingleVal = function (adapterName, attribute, ruleName) {
  281.         /// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where
  282.         /// the jQuery Validate validation rule has a single value.</summary>
  283.         /// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
  284.         /// in the data-val-nnnn HTML attribute(where nnnn is the adapter name).</param>
  285.         /// <param name="attribute" type="String">[Optional] The name of the HTML attribute that contains the value.
  286.         /// The default is "val".</param>
  287.         /// <param name="ruleName" type="String" optional="true">[Optional] The name of the jQuery Validate rule. If not provided, the value
  288.         /// of adapterName will be used instead.</param>
  289.         /// <returns type="jQuery.validator.unobtrusive.adapters" />
  290.         return this.add(adapterName, [attribute || "val"], function (options) {
  291.             setValidationValues(options, ruleName || adapterName, options.params[attribute]);
  292.         });
  293.     };
  294.  
  295.     $jQval.addMethod("__dummy__", function (value, element, params) {
  296.         return true;
  297.     });
  298.  
  299.     $jQval.addMethod("regex", function (value, element, params) {
  300.         var match;
  301.         if (this.optional(element)) {
  302.             return true;
  303.         }
  304.  
  305.         match = new RegExp(params).exec(value);
  306.         return (match && (match.index === 0) && (match[0].length === value.length));
  307.     });
  308.  
  309.     $jQval.addMethod("nonalphamin", function (value, element, nonalphamin) {
  310.         var match;
  311.         if (nonalphamin) {
  312.             match = value.match(/\W/g);
  313.             match = match && match.length >= nonalphamin;
  314.         }
  315.         return match;
  316.     });
  317.  
  318.     adapters.addSingleVal("accept", "exts").addSingleVal("regex", "pattern");
  319.     adapters.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url");
  320.     adapters.addMinMax("length", "minlength", "maxlength", "rangelength").addMinMax("range", "min", "max", "range");
  321.     adapters.add("equalto", ["other"], function (options) {
  322.         var prefix = getModelPrefix(options.element.name),
  323.             other = options.params.other,
  324.             fullOtherName = appendModelPrefix(other, prefix),
  325.             element = $(options.form).find(":input[name='" + escapeAttributeValue(fullOtherName) + "']")[0];
  326.  
  327.         setValidationValues(options, "equalTo", element);
  328.     });
  329.     adapters.add("required", function (options) {
  330.         // jQuery Validate equates "required" with "mandatory" for checkbox elements
  331.         if (options.element.tagName.toUpperCase() !== "INPUT" || options.element.type.toUpperCase() !== "CHECKBOX") {
  332.             setValidationValues(options, "required", true);
  333.         }
  334.     });
  335.     adapters.add("remote", ["url", "type", "additionalfields"], function (options) {
  336.         var value = {
  337.             url: options.params.url,
  338.             type: options.params.type || "GET",
  339.             data: {}
  340.         },
  341.             prefix = getModelPrefix(options.element.name);
  342.  
  343.         $.each(splitAndTrim(options.params.additionalfields || options.element.name), function (i, fieldName) {
  344.             var paramName = appendModelPrefix(fieldName, prefix);
  345.             value.data[paramName] = function () {
  346.                 return $(options.form).find(":input[name='" + escapeAttributeValue(paramName) + "']").val();
  347.             };
  348.         });
  349.  
  350.         setValidationValues(options, "remote", value);
  351.     });
  352.     adapters.add("password", ["min", "nonalphamin", "regex"], function (options) {
  353.         if (options.params.min) {
  354.             setValidationValues(options, "minlength", options.params.min);
  355.         }
  356.         if (options.params.nonalphamin) {
  357.             setValidationValues(options, "nonalphamin", options.params.nonalphamin);
  358.         }
  359.         if (options.params.regex) {
  360.             setValidationValues(options, "regex", options.params.regex);
  361.         }
  362.     });
  363.  
  364.     $(function () {
  365.         $jQval.unobtrusive.parse(document);
  366.     });
  367. } (jQuery));