Viewing File: /usr/local/cpanel/share/libraries/cjt2/src/directives/validationContainerDirective.js

/*
# cjt/directives/validationContainerDirective.js                   Copyright 2022 cPanel, L.L.C.
#                                                           All rights reserved.
# copyright@cpanel.net                                         http://cpanel.net
# This code is subject to the cPanel license. Unauthorized copying is prohibited
*/

define(
    [
        "angular",
        "cjt/core",
        "ngSanitize",
        "cjt/templates" // NOTE: Pre-load the template cache
    ],
    function(angular, CJT) {

        "use strict";

        var module = angular.module("cjt2.directives.validationContainer", [
            "ngSanitize", "cjt2.templates"
        ]);

        /**
         * Directive that shows a alert.
         * @example
         *
         * To bind to a fields standard and extended validation errors:
         *   <ul validation-container field-name="textField">
         *       <li validation-item field-name="textField" validation-name="required">
         *           The textField is required.
         *       </li>
         *   </ul>
         *
         * To bind to a fields extended validation errors:
         *   <ul validation-container field-name="textField">
         *   </ul>
         *
         * To add a custom prefix to the item ids:
         *   <ul validation-container field-name="textField" prefix="foo">
         *   </ul>
         *
         * To take over rendering of the items manually use:
         *   <style>
         *   .bullet::before {
         *       content: "•";
         *       padding-right: 10px;
         *       font-weight: bold;
         *       font-size: larger;
         *   }
         *   </style>
         *   <ul validation-container field-name="textField" manual>
         *      <validation-item field-name="textField" validation-name="cidr"></validation-item>
         *      <validation-item field-name="textField" validation-name="cidr-details" no-icon prefix-class="bullet"></validation-item>
         *   </ul>
         */
        module.directive("validationContainer", ["$log", function($log) {

            var RELATIVE_PATH = "libraries/cjt2/directives/validationContainer.phtml";

            /**
             * Dynamically fetch and cache the field. Caches the field in scope
             * along with the needed errors and extendedErrors collections.
             *
             * @method  _attachField
             * @private
             * @param  {ngForm} form      Form to which the field is attached.
             * @param  {String} fieldName Name of the field we are monitoring.
             * @param  {Scope}  scope     Scope
             * @return {ngField}
             */
            function _attachField(form, fieldName, scope) {
                var field = scope.field;
                if (!field) {
                    field = form[fieldName];
                    if (field) {
                        scope.field = field;
                        scope.errors = field.$error;
                        scope.extendedErrors = field.$error_details;
                    }
                }
                return field;
            }

            return {
                restrict: "EA",
                templateUrl: CJT.config.debug ? CJT.buildFullPath(RELATIVE_PATH) : RELATIVE_PATH,
                replace: true,
                transclude: true,
                scope: true,
                link: function( scope, element, attrs ) {
                    var form = element.controller("form");
                    var fieldName = scope.$eval(attrs.fieldName) || attrs.fieldName;
                    var manual = angular.isDefined(attrs.manual) ? true : false;
                    var prefix = scope.$eval(attrs.prefix) || attrs.prefix || "validator";
                    var showWhenPristine = scope.$eval(attrs.showWhenPristine) || false;
                    var field = _attachField(form, fieldName, scope);

                    /**
                     * Determine if the item can be shown
                     *
                     * @method canShow
                     * @return {Boolean}
                     */
                    scope.canShow = function() {

                        field = _attachField(form, fieldName, scope);
                        if (!field) {
                            return false;
                        }

                        return (!field.$pristine || showWhenPristine || form.$submitted) && field.$invalid;
                    };

                    /**
                     * Determine if the line item  within the item should be shown
                     *
                     * @method canShowItem
                     * @param  {String} key Validation key name.
                     * @return {Boolean}
                     */
                    scope.canShowItem = function(key) {
                        if (manual) {
                            return false;
                        }

                        field = _attachField(form, fieldName, scope);
                        if (!field) {
                            return false;
                        }

                        return scope.errors[key] !== false && scope.hasExtendedError(key);
                    };

                    /**
                     * Gets a list of all validation failure message objects for the field.
                     *
                     * @method aggregateMessages
                     * @return {Array}   An aggregated list of modified ValidationResult objects that
                     *                   are  given "id" and "validatorName" properties
                     */
                    scope.aggregateMessages = function() {

                        field = _attachField(form, fieldName, scope);
                        var messages = [];

                        angular.forEach(scope.errors, function(isInvalid, validatorName) {
                            var messageSet = _getMessageSet(validatorName);
                            if (isInvalid && messageSet) {
                                var setLength = messageSet.length;
                                messageSet.forEach(function(message) {
                                    message.validatorName = validatorName;

                                    // If there is only a single message from the set, we can use the shorter form of the ID.
                                    // This is mainly here to maintain backwards compatability.
                                    message.id = setLength > 1 ? _generateId(validatorName, message.name) : _generateId(validatorName);
                                    messages.push(message);
                                });
                            } else if (isInvalid) {

                                // Invalid but no message set, provides debug info for developer to fix their validator
                                CJT.debug("[cjt2.directives.validationContainer] “" + validatorName + "” is invalid, but does not have a validation message provided. Ensure inline message was created.");
                            }
                        });

                        return messages;
                    };

                    /**
                     * Gets the set of message objects for a particular validator on the field.
                     *
                     * @method _getMessageSet
                     * @private
                     * @param  {String} validatorName   The name of the validator whose messages you wish to fetch
                     * @return {Array}                  An array of ValidationResult objects
                     */
                    function _getMessageSet(validatorName) {
                        if ((field.$pristine && !showWhenPristine) || field.$valid) {
                            return;
                        }

                        if (field.$error_details) {
                            var details = field.$error_details.get(validatorName);
                            if ( details && details.hasMessages() ) {
                                return details.get();
                            } else {
                                return false;
                            }
                        }
                    }


                    /**
                     * Check if the field has extended error information for the key
                     *
                     * @method hasExtendedError
                     * @param  {String}  key Name of the category to look at.
                     * @return {Boolean}     true if has extended error information, false otherwise.
                     */
                    scope.hasExtendedError = function(key) {
                        field = _attachField(form, fieldName, scope);

                        if (field.$error_details) {
                            var details = field.$error_details.get(key);
                            if ( details && details.hasMessages() ) {
                                return true;
                            }
                        }
                        return false;
                    };

                    /**
                     * Returns a generated id for the item.
                     *
                     * @method _generateId
                     * @private
                     * @param {String} validatorName   The name of the validator
                     * @param {String} [errorName]     Optional. The name of the error/rule within the
                     *                                 validator that prompted its validation failure.
                     *                                 This should be provided if there the validator
                     *                                 adds multiple messages to its ValidationResult.
                     * @return {String}
                     */
                    function _generateId(validatorName, errorName) {
                        if (errorName) {
                            return prefix + "_" + fieldName + "_" + validatorName + "_" + errorName;
                        } else {
                            return prefix + "_" + validatorName;
                        }
                    }
                }
            };
        }]);
    }
);
Back to Directory File Manager