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

/*
# cjt/directives/limitRange.js                      Copyright(c) 2020 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
*/
/* global define: false */

define(
    [
        "angular",
        "cjt/core",
        "lodash"
    ],
    function(angular, CJT, _) {

        // Constants
        var SCOPE_DECLARATION = {
            rangeMinimum: "@rangeMinimum",
            rangeMaximum: "@rangeMaximum",
            rangeDefault: "@rangeDefault"
        };

        var module = angular.module("cjt2.directives.limitRange", []);

        /**
         * Directive that prevents numeric inputs from going outside an integer range.
         * @attribute {Number}  rangeMinimum - minimum value allowed.
         * @attribute {Number}  rangeMaximum - maximum value allowed.
         * @attribute {Number}  rangeDefault - default value to us if the field is invalid.
         * @example
         * <input limit-range range-minimum="1" range-maximum="10" />
         */
        module.directive("limitRange", [ function() {
            return {
                restrict: "A",
                require: "?ngModel",
                scope: SCOPE_DECLARATION,
                link: function(scope, element, attrs, model) {

                    /* Apply range restrictions on blur. This is better than trying to apply them
                     * immediately because a partially-typed number might fall outside of the allowable
                     * range, causing unexpected behavior. */
                    element.bind("blur", function(e) {

                        var minimum = _parseIntOrDefault(scope.rangeMinimum, null);
                        var maximum = _parseIntOrDefault(scope.rangeMaximum, null);

                        if (!this.value) {
                            this.value = _parseIntOrDefault(scope.rangeDefault, 1);
                        }

                        if (minimum !== null) {
                            if (this.value < minimum) {
                                this.value = minimum;
                            }
                        }

                        if (maximum !== null) {
                            if (this.value > maximum) {
                                this.value = maximum;
                            }
                        }

                        _update(model, this.value);
                    });

                    // Only allow the navigation keys and the number keys
                    // Key code reference: https://css-tricks.com/snippets/javascript/javascript-keycodes/
                    element.on("keydown", function(event) {

                        // Cursor movements and delete/backspace
                        if (_.includes([
                            8,  // backspace
                            9,  // tab
                            13, // return/enter
                            33, // page up
                            34, // page down
                            35, // end
                            36, // home
                            37, // left arrow
                            38, // up arrow
                            39, // right arrow
                            40, // down arrow
                            45, // insert - can be used for cut/paste
                            46  // delete
                        ], event.keyCode)) {
                            return true;
                        }

                        // Numbers, both keypad and main number keys.
                        if ((event.keyCode >= 48 && event.keyCode <= 57) || (event.keyCode >= 96 && event.keyCode <= 105)) {
                            return true;
                        }

                        // Cut and paste: CTRL-c, CTRL-v, CTRL-x
                        if ((event.ctrlKey || event.metaKey) && (event.keyCode === 67 || event.keyCode === 86 || event.keyCode === 88)) {
                            return true;
                        }

                        // Otherwise, cancel the event
                        event.preventDefault();
                        return false;
                    });
                }
            };
        }]);

        /**
         * Parse the string as an integer. If it does not return a number, use the default instead.
         * @param  {String} string
         * @param  {Number} defaultValue
         * @return {Number}
         */
        function _parseIntOrDefault(string, defaultValue) {
            var parsed = parseInt(string, 10); // parseInt returns NaN with undefined, null, or empty strings
            return isNaN(parsed) ? defaultValue : parsed;
        }

        /**
         * If the model exists, update the model with the dynamically set value and revalidate.
         * @param  {Object} model
         * @param  {Any} value
         */
        function _update(model, value) {
            if (model) {
                model.$setViewValue(value);
                model.$validate();
            }
        }

    });
Back to Directory File Manager