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

/*
# cjt/directives/toggleSwitchDirective.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",
        "lodash",
        "cjt/core",
        "cjt/util/test",
        "uiBootstrap",
        "cjt/directives/spinnerDirective",
        "cjt/templates" // NOTE: Pre-load the template cache
    ],
    function(angular, _, CJT, TEST) {

        "use strict";

        var module = angular.module("cjt2.directives.toggleSwitch", [
            "cjt2.templates",
            "cjt2.directives.spinner"
        ]);

        /**
         * Directive that renders a toggle switch
         * @attribute {String}  id -
         * @attribute {String}  enabledLabel
         * @attribute {String}  disabledLabel
         * @attribute {String}  labelPosition - one of right, left, none
         * @attribute {String}  spinnerPosition - one of right, left
         * @attribute {Boolean} noSpinner - true or false, if true will suppress the spinner.
         * @attribute {String}  ariaLabel
         * @attribute {Binding} ngDisabled
         * @attribute {Binding} ngModel - required
         * @attribute {Function} onToggle - required to make the switch toggle on click. You must provide this and it
         * must handle the needed state change to trigger a toggle effect.
         * @example
         * <toggle-switch ng-model="state" on-toggle="state = !state" />
         */
        module.directive("toggleSwitch", ["spinnerAPI",
            function(spinnerAPI) {

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


                return {
                    restrict: "E",
                    templateUrl: CJT.config.debug ? CJT.buildFullPath(RELATIVE_PATH) : RELATIVE_PATH,
                    require: "ngModel",
                    replace: true,
                    scope: {
                        parentID: "@id",
                        enabledLabel: "@",
                        disabledLabel: "@",
                        labelPosition: "@",
                        spinnerPosition: "@",
                        ariaLabel: "@",
                        isDisabled: "=ngDisabled",
                        ngModel: "=",
                        onToggle: "&",
                    },
                    link: function(scope, elem, attrs) {

                        scope.noSpinner = attrs.noSpinner === "true" || attrs.noSpinner === "1";
                        scope.spinnerId = scope.parentID + "_toggle_spinner";
                        if (!scope.labelPosition) {
                            scope.labelPosition = "right"; // To preserve behavior that existed
                        } else if (!_.includes(["left", "right", "none"], scope.labelPosition)) {
                            throw "Invalid label-position set: " + scope.labelPosition + ". Must be one of: left, right, none.";
                        }

                        if (!scope.spinnerPosition) {
                            scope.spinnerPosition = "right"; // To preserve behavior that existed
                        } else if (!_.includes(["left", "right"], scope.spinnerPosition)) {
                            throw "Invalid label-position set: " + scope.spinnerPosition + ". Must be one of: left or right.";
                        }

                        scope.noLabel = (!scope.enabledLabel && !scope.disabledLabel) || scope.labelPosition === "none";

                        scope.handle_keydown = function(event) {

                            // prevent the spacebar from scrolling the window
                            if (event.keyCode === 32) {
                                event.preventDefault();
                            }
                        };

                        scope.handle_keyup = function(event) {

                            // bind to the spacebar and enter keys to toggle the field
                            if (event.keyCode === 32 || event.keyCode === 13) {
                                event.preventDefault();
                                scope.toggle_status();
                            }

                            // bind left arrow to turn off
                            if (event.keyCode === 37) {
                                event.preventDefault();
                                if (scope.ngModel) {
                                    scope.toggle_status();
                                }
                            }

                            // bind right arrow to turn on
                            if (event.keyCode === 39) {
                                event.preventDefault();
                                if (!scope.ngModel) {
                                    scope.toggle_status();
                                }
                            }
                        };

                        scope.get_aria_value = function() {
                            return scope.ngModel ? "true" : "false";
                        };

                        /**
                         * Start the spinner if needed
                         */
                        var _startSpinner = function() {
                            if (!scope.noSpinner) {
                                spinnerAPI.start(scope.spinnerId, false);
                            }
                        };

                        /**
                         * Stop the spinner if needed
                         */
                        var _stopSpinner = function() {
                            if (!scope.noSpinner) {
                                spinnerAPI.stop(scope.spinnerId, false);
                            }
                        };

                        scope.toggle_status = function() {
                            if (scope.changing_status || scope.isDisabled) {
                                return;
                            }

                            scope.changing_status = true;
                            _startSpinner();

                            var promise = scope.onToggle();
                            if (TEST.isQPromise(promise)) {
                                promise.finally(function() {
                                    scope.changing_status = false;
                                    _stopSpinner();
                                });
                            } else {
                                scope.changing_status = false;
                                _stopSpinner();
                            }
                        };
                    }
                };
            }
        ]);
    }
);
Back to Directory File Manager