cscg24-photoeditor

CSCG 2024 Challenge 'PhotoEditor'
git clone https://git.sinitax.com/sinitax/cscg24-photoeditor
Log | Files | Refs | sfeed.txt

jquery.validate.unobtrusive.js (19385B)


      1/**
      2 * @license
      3 * Unobtrusive validation support library for jQuery and jQuery Validate
      4 * Copyright (c) .NET Foundation. All rights reserved.
      5 * Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
      6 * @version v4.0.0
      7 */
      8
      9/*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 */
     10/*global document: false, jQuery: false */
     11
     12(function (factory) {
     13    if (typeof define === 'function' && define.amd) {
     14        // AMD. Register as an anonymous module.
     15        define("jquery.validate.unobtrusive", ['jquery-validation'], factory);
     16    } else if (typeof module === 'object' && module.exports) {
     17        // CommonJS-like environments that support module.exports     
     18        module.exports = factory(require('jquery-validation'));
     19    } else {
     20        // Browser global
     21        jQuery.validator.unobtrusive = factory(jQuery);
     22    }
     23}(function ($) {
     24    var $jQval = $.validator,
     25        adapters,
     26        data_validation = "unobtrusiveValidation";
     27
     28    function setValidationValues(options, ruleName, value) {
     29        options.rules[ruleName] = value;
     30        if (options.message) {
     31            options.messages[ruleName] = options.message;
     32        }
     33    }
     34
     35    function splitAndTrim(value) {
     36        return value.replace(/^\s+|\s+$/g, "").split(/\s*,\s*/g);
     37    }
     38
     39    function escapeAttributeValue(value) {
     40        // As mentioned on http://api.jquery.com/category/selectors/
     41        return value.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g, "\\$1");
     42    }
     43
     44    function getModelPrefix(fieldName) {
     45        return fieldName.substr(0, fieldName.lastIndexOf(".") + 1);
     46    }
     47
     48    function appendModelPrefix(value, prefix) {
     49        if (value.indexOf("*.") === 0) {
     50            value = value.replace("*.", prefix);
     51        }
     52        return value;
     53    }
     54
     55    function onError(error, inputElement) {  // 'this' is the form element
     56        var container = $(this).find("[data-valmsg-for='" + escapeAttributeValue(inputElement[0].name) + "']"),
     57            replaceAttrValue = container.attr("data-valmsg-replace"),
     58            replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) !== false : null;
     59
     60        container.removeClass("field-validation-valid").addClass("field-validation-error");
     61        error.data("unobtrusiveContainer", container);
     62
     63        if (replace) {
     64            container.empty();
     65            error.removeClass("input-validation-error").appendTo(container);
     66        }
     67        else {
     68            error.hide();
     69        }
     70    }
     71
     72    function onErrors(event, validator) {  // 'this' is the form element
     73        var container = $(this).find("[data-valmsg-summary=true]"),
     74            list = container.find("ul");
     75
     76        if (list && list.length && validator.errorList.length) {
     77            list.empty();
     78            container.addClass("validation-summary-errors").removeClass("validation-summary-valid");
     79
     80            $.each(validator.errorList, function () {
     81                $("<li />").html(this.message).appendTo(list);
     82            });
     83        }
     84    }
     85
     86    function onSuccess(error) {  // 'this' is the form element
     87        var container = error.data("unobtrusiveContainer");
     88
     89        if (container) {
     90            var replaceAttrValue = container.attr("data-valmsg-replace"),
     91                replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) : null;
     92
     93            container.addClass("field-validation-valid").removeClass("field-validation-error");
     94            error.removeData("unobtrusiveContainer");
     95
     96            if (replace) {
     97                container.empty();
     98            }
     99        }
    100    }
    101
    102    function onReset(event) {  // 'this' is the form element
    103        var $form = $(this),
    104            key = '__jquery_unobtrusive_validation_form_reset';
    105        if ($form.data(key)) {
    106            return;
    107        }
    108        // Set a flag that indicates we're currently resetting the form.
    109        $form.data(key, true);
    110        try {
    111            $form.data("validator").resetForm();
    112        } finally {
    113            $form.removeData(key);
    114        }
    115
    116        $form.find(".validation-summary-errors")
    117            .addClass("validation-summary-valid")
    118            .removeClass("validation-summary-errors");
    119        $form.find(".field-validation-error")
    120            .addClass("field-validation-valid")
    121            .removeClass("field-validation-error")
    122            .removeData("unobtrusiveContainer")
    123            .find(">*")  // If we were using valmsg-replace, get the underlying error
    124            .removeData("unobtrusiveContainer");
    125    }
    126
    127    function validationInfo(form) {
    128        var $form = $(form),
    129            result = $form.data(data_validation),
    130            onResetProxy = $.proxy(onReset, form),
    131            defaultOptions = $jQval.unobtrusive.options || {},
    132            execInContext = function (name, args) {
    133                var func = defaultOptions[name];
    134                func && $.isFunction(func) && func.apply(form, args);
    135            };
    136
    137        if (!result) {
    138            result = {
    139                options: {  // options structure passed to jQuery Validate's validate() method
    140                    errorClass: defaultOptions.errorClass || "input-validation-error",
    141                    errorElement: defaultOptions.errorElement || "span",
    142                    errorPlacement: function () {
    143                        onError.apply(form, arguments);
    144                        execInContext("errorPlacement", arguments);
    145                    },
    146                    invalidHandler: function () {
    147                        onErrors.apply(form, arguments);
    148                        execInContext("invalidHandler", arguments);
    149                    },
    150                    messages: {},
    151                    rules: {},
    152                    success: function () {
    153                        onSuccess.apply(form, arguments);
    154                        execInContext("success", arguments);
    155                    }
    156                },
    157                attachValidation: function () {
    158                    $form
    159                        .off("reset." + data_validation, onResetProxy)
    160                        .on("reset." + data_validation, onResetProxy)
    161                        .validate(this.options);
    162                },
    163                validate: function () {  // a validation function that is called by unobtrusive Ajax
    164                    $form.validate();
    165                    return $form.valid();
    166                }
    167            };
    168            $form.data(data_validation, result);
    169        }
    170
    171        return result;
    172    }
    173
    174    $jQval.unobtrusive = {
    175        adapters: [],
    176
    177        parseElement: function (element, skipAttach) {
    178            /// <summary>
    179            /// Parses a single HTML element for unobtrusive validation attributes.
    180            /// </summary>
    181            /// <param name="element" domElement="true">The HTML element to be parsed.</param>
    182            /// <param name="skipAttach" type="Boolean">[Optional] true to skip attaching the
    183            /// validation to the form. If parsing just this single element, you should specify true.
    184            /// If parsing several elements, you should specify false, and manually attach the validation
    185            /// to the form when you are finished. The default is false.</param>
    186            var $element = $(element),
    187                form = $element.parents("form")[0],
    188                valInfo, rules, messages;
    189
    190            if (!form) {  // Cannot do client-side validation without a form
    191                return;
    192            }
    193
    194            valInfo = validationInfo(form);
    195            valInfo.options.rules[element.name] = rules = {};
    196            valInfo.options.messages[element.name] = messages = {};
    197
    198            $.each(this.adapters, function () {
    199                var prefix = "data-val-" + this.name,
    200                    message = $element.attr(prefix),
    201                    paramValues = {};
    202
    203                if (message !== undefined) {  // Compare against undefined, because an empty message is legal (and falsy)
    204                    prefix += "-";
    205
    206                    $.each(this.params, function () {
    207                        paramValues[this] = $element.attr(prefix + this);
    208                    });
    209
    210                    this.adapt({
    211                        element: element,
    212                        form: form,
    213                        message: message,
    214                        params: paramValues,
    215                        rules: rules,
    216                        messages: messages
    217                    });
    218                }
    219            });
    220
    221            $.extend(rules, { "__dummy__": true });
    222
    223            if (!skipAttach) {
    224                valInfo.attachValidation();
    225            }
    226        },
    227
    228        parse: function (selector) {
    229            /// <summary>
    230            /// Parses all the HTML elements in the specified selector. It looks for input elements decorated
    231            /// with the [data-val=true] attribute value and enables validation according to the data-val-*
    232            /// attribute values.
    233            /// </summary>
    234            /// <param name="selector" type="String">Any valid jQuery selector.</param>
    235
    236            // $forms includes all forms in selector's DOM hierarchy (parent, children and self) that have at least one
    237            // element with data-val=true
    238            var $selector = $(selector),
    239                $forms = $selector.parents()
    240                    .addBack()
    241                    .filter("form")
    242                    .add($selector.find("form"))
    243                    .has("[data-val=true]");
    244
    245            $selector.find("[data-val=true]").each(function () {
    246                $jQval.unobtrusive.parseElement(this, true);
    247            });
    248
    249            $forms.each(function () {
    250                var info = validationInfo(this);
    251                if (info) {
    252                    info.attachValidation();
    253                }
    254            });
    255        }
    256    };
    257
    258    adapters = $jQval.unobtrusive.adapters;
    259
    260    adapters.add = function (adapterName, params, fn) {
    261        /// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation.</summary>
    262        /// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
    263        /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).</param>
    264        /// <param name="params" type="Array" optional="true">[Optional] An array of parameter names (strings) that will
    265        /// be extracted from the data-val-nnnn-mmmm HTML attributes (where nnnn is the adapter name, and
    266        /// mmmm is the parameter name).</param>
    267        /// <param name="fn" type="Function">The function to call, which adapts the values from the HTML
    268        /// attributes into jQuery Validate rules and/or messages.</param>
    269        /// <returns type="jQuery.validator.unobtrusive.adapters" />
    270        if (!fn) {  // Called with no params, just a function
    271            fn = params;
    272            params = [];
    273        }
    274        this.push({ name: adapterName, params: params, adapt: fn });
    275        return this;
    276    };
    277
    278    adapters.addBool = function (adapterName, ruleName) {
    279        /// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where
    280        /// the jQuery Validate validation rule has no parameter values.</summary>
    281        /// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
    282        /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).</param>
    283        /// <param name="ruleName" type="String" optional="true">[Optional] The name of the jQuery Validate rule. If not provided, the value
    284        /// of adapterName will be used instead.</param>
    285        /// <returns type="jQuery.validator.unobtrusive.adapters" />
    286        return this.add(adapterName, function (options) {
    287            setValidationValues(options, ruleName || adapterName, true);
    288        });
    289    };
    290
    291    adapters.addMinMax = function (adapterName, minRuleName, maxRuleName, minMaxRuleName, minAttribute, maxAttribute) {
    292        /// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where
    293        /// the jQuery Validate validation has three potential rules (one for min-only, one for max-only, and
    294        /// one for min-and-max). The HTML parameters are expected to be named -min and -max.</summary>
    295        /// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
    296        /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).</param>
    297        /// <param name="minRuleName" type="String">The name of the jQuery Validate rule to be used when you only
    298        /// have a minimum value.</param>
    299        /// <param name="maxRuleName" type="String">The name of the jQuery Validate rule to be used when you only
    300        /// have a maximum value.</param>
    301        /// <param name="minMaxRuleName" type="String">The name of the jQuery Validate rule to be used when you
    302        /// have both a minimum and maximum value.</param>
    303        /// <param name="minAttribute" type="String" optional="true">[Optional] The name of the HTML attribute that
    304        /// contains the minimum value. The default is "min".</param>
    305        /// <param name="maxAttribute" type="String" optional="true">[Optional] The name of the HTML attribute that
    306        /// contains the maximum value. The default is "max".</param>
    307        /// <returns type="jQuery.validator.unobtrusive.adapters" />
    308        return this.add(adapterName, [minAttribute || "min", maxAttribute || "max"], function (options) {
    309            var min = options.params.min,
    310                max = options.params.max;
    311
    312            if (min && max) {
    313                setValidationValues(options, minMaxRuleName, [min, max]);
    314            }
    315            else if (min) {
    316                setValidationValues(options, minRuleName, min);
    317            }
    318            else if (max) {
    319                setValidationValues(options, maxRuleName, max);
    320            }
    321        });
    322    };
    323
    324    adapters.addSingleVal = function (adapterName, attribute, ruleName) {
    325        /// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where
    326        /// the jQuery Validate validation rule has a single value.</summary>
    327        /// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
    328        /// in the data-val-nnnn HTML attribute(where nnnn is the adapter name).</param>
    329        /// <param name="attribute" type="String">[Optional] The name of the HTML attribute that contains the value.
    330        /// The default is "val".</param>
    331        /// <param name="ruleName" type="String" optional="true">[Optional] The name of the jQuery Validate rule. If not provided, the value
    332        /// of adapterName will be used instead.</param>
    333        /// <returns type="jQuery.validator.unobtrusive.adapters" />
    334        return this.add(adapterName, [attribute || "val"], function (options) {
    335            setValidationValues(options, ruleName || adapterName, options.params[attribute]);
    336        });
    337    };
    338
    339    $jQval.addMethod("__dummy__", function (value, element, params) {
    340        return true;
    341    });
    342
    343    $jQval.addMethod("regex", function (value, element, params) {
    344        var match;
    345        if (this.optional(element)) {
    346            return true;
    347        }
    348
    349        match = new RegExp(params).exec(value);
    350        return (match && (match.index === 0) && (match[0].length === value.length));
    351    });
    352
    353    $jQval.addMethod("nonalphamin", function (value, element, nonalphamin) {
    354        var match;
    355        if (nonalphamin) {
    356            match = value.match(/\W/g);
    357            match = match && match.length >= nonalphamin;
    358        }
    359        return match;
    360    });
    361
    362    if ($jQval.methods.extension) {
    363        adapters.addSingleVal("accept", "mimtype");
    364        adapters.addSingleVal("extension", "extension");
    365    } else {
    366        // for backward compatibility, when the 'extension' validation method does not exist, such as with versions
    367        // of JQuery Validation plugin prior to 1.10, we should use the 'accept' method for
    368        // validating the extension, and ignore mime-type validations as they are not supported.
    369        adapters.addSingleVal("extension", "extension", "accept");
    370    }
    371
    372    adapters.addSingleVal("regex", "pattern");
    373    adapters.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url");
    374    adapters.addMinMax("length", "minlength", "maxlength", "rangelength").addMinMax("range", "min", "max", "range");
    375    adapters.addMinMax("minlength", "minlength").addMinMax("maxlength", "minlength", "maxlength");
    376    adapters.add("equalto", ["other"], function (options) {
    377        var prefix = getModelPrefix(options.element.name),
    378            other = options.params.other,
    379            fullOtherName = appendModelPrefix(other, prefix),
    380            element = $(options.form).find(":input").filter("[name='" + escapeAttributeValue(fullOtherName) + "']")[0];
    381
    382        setValidationValues(options, "equalTo", element);
    383    });
    384    adapters.add("required", function (options) {
    385        // jQuery Validate equates "required" with "mandatory" for checkbox elements
    386        if (options.element.tagName.toUpperCase() !== "INPUT" || options.element.type.toUpperCase() !== "CHECKBOX") {
    387            setValidationValues(options, "required", true);
    388        }
    389    });
    390    adapters.add("remote", ["url", "type", "additionalfields"], function (options) {
    391        var value = {
    392            url: options.params.url,
    393            type: options.params.type || "GET",
    394            data: {}
    395        },
    396            prefix = getModelPrefix(options.element.name);
    397
    398        $.each(splitAndTrim(options.params.additionalfields || options.element.name), function (i, fieldName) {
    399            var paramName = appendModelPrefix(fieldName, prefix);
    400            value.data[paramName] = function () {
    401                var field = $(options.form).find(":input").filter("[name='" + escapeAttributeValue(paramName) + "']");
    402                // For checkboxes and radio buttons, only pick up values from checked fields.
    403                if (field.is(":checkbox")) {
    404                    return field.filter(":checked").val() || field.filter(":hidden").val() || '';
    405                }
    406                else if (field.is(":radio")) {
    407                    return field.filter(":checked").val() || '';
    408                }
    409                return field.val();
    410            };
    411        });
    412
    413        setValidationValues(options, "remote", value);
    414    });
    415    adapters.add("password", ["min", "nonalphamin", "regex"], function (options) {
    416        if (options.params.min) {
    417            setValidationValues(options, "minlength", options.params.min);
    418        }
    419        if (options.params.nonalphamin) {
    420            setValidationValues(options, "nonalphamin", options.params.nonalphamin);
    421        }
    422        if (options.params.regex) {
    423            setValidationValues(options, "regex", options.params.regex);
    424        }
    425    });
    426    adapters.add("fileextensions", ["extensions"], function (options) {
    427        setValidationValues(options, "extension", options.params.extensions);
    428    });
    429
    430    $(function () {
    431        $jQval.unobtrusive.parse(document);
    432    });
    433
    434    return $jQval.unobtrusive;
    435}));