Viewing File: /usr/local/cpanel/whostmgr/docroot/templates/master_templates/support.js

/*
# master_templates/master.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
*/

(function(window) {
    "use strict";

    /**
     * Helper class to manage slide out menus. The container passed, must
     * have a .slideContainer, a .slideTab and a .slidPanel element.
     *
     * @class SlideMenu
     * @param {string} containerId Container where the SlideMenu will run.
     */
    var SlideMenu = function(containerId) {

        this.supportContainer = document.getElementById(containerId);
        this.slideToggleClass = "show";
        this.slideIcon = null;
        this.slideIconLink = null;
        this.slidePanel = null;
    };

    SlideMenu.prototype = {

        /**
         * Initializes the slide menu for the given container.
         *
         * @method init
         */
        init: function() {
            if (this.supportContainer !== null) {
                this.slideContainer = this.supportContainer.querySelector(".slideContainer");
                this.slideIcon = this.supportContainer.querySelector(".slideTab");
                this.slideIconLink = this.supportContainer.querySelector(".slideTab a");
                this.slidePanel = this.slideContainer.querySelector(".slidePanel");
                this._attachEvents();
                this.initializeGlobalListeners();
            }
        },

        /**
         * Helps in attaching events to the slide icon click & mouse out.
         *
         * @method _attachEvents ( private method )
         */
        _attachEvents: function() {

            // called when window has loaded.
            // attach events to links on the page. Send the current SlideMenu instance as
            // an added argument

            var slideMenu = this;

            this.slideIcon.addEventListener("click", function() {
                slideMenu.handleIconClick();
            }, false);
        },

        /**
         * Initializes keys that need to be recognized across all frames
         *
         * @method initializeGlobalListeners
         */
        initializeGlobalListeners: function() {
            var frames = this.getAllFrames();
            var slideObj = this;

            var handleKeyDown = function(keyEvent) {

                // keyCode 113 is F2 key
                if (keyEvent.keyCode === 113 && keyEvent.altKey) {
                    slideObj.handleSupportKey(keyEvent, slideObj);
                }
            };

            // Build our globalKeyListener object using the context of our available frames
            for (var i = 0, len = frames.length; i < len; i++) {

                // Case 82249: The Lastpass Chrome extension creates a (hidden)
                // frame on the webpage that is accessed in this loop.  This causes
                // a security error, since an https:// protocol frame is accessing
                // data from a non-https:// frame.  The uncaught exception prevents
                // pages like "installssl" in WHM from fully running, breaking
                // functionality.
                try {
                    frames[i].document.addEventListener("keydown", handleKeyDown, false);
                } catch (e) {

                    // Do Nothing
                }
            }
        },

        /**
         * Utility method to check to see whether a HTMLElement uses a specific class.
         *
         * @method hasClass
         * @element {HTMLElement} element to check
         * @classToCheck {string} class name to check
         */
        hasClass: function(element, classToCheck) {
            return element.className.indexOf(classToCheck) > -1;
        },

        /**
         * Utility method to add a class to a HTMLElement.
         *
         * @method addClass
         * @element {HTMLElement} element to modify
         * @classToAdd {string} class name to add to className property
         */
        addClass: function(element, classToAdd) {
            var classNames = element.className.split(" ");

            if (classNames.indexOf(classToAdd) === -1) {
                classNames.push(classToAdd);
                element.className = classNames.join(" ");
            }
        },

        /**
         * Utility method to remove a class from a HTMLElement.
         *
         * @method removeClass
         * @element {HTMLElement} element to modify
         * @classToRemove {string} class name to remove from className property
         */
        removeClass: function(element, classToRemove) {
            var classNames = element.className.split(" ");
            var stylePosition = classNames.indexOf(classToRemove);

            if (stylePosition > -1) {
                classNames = classNames.splice(stylePosition - 1, 1);
                element.className = classNames.join(" ");
            }
        },

        /**
         * Event handler for the slide tab focus event. This adds a hover style to the slide icon.
         *
         * @method handleSlideTabFocus
         * @e {object} slide link's focus event
         */
        handleSlideTabFocus: function() {
            this.addClass(this.slideIcon, "active");
        },

        /**
         * Event handler for the slide link's blur event. This removes the hover style to the slide icon.
         *
         * @method handleSlideTabBlur
         * @e {object} slide link's blur event
         */
        handleSlideTabBlur: function() {
            this.removeClass(this.slideIcon, "active");
        },

        /**
         * Event handler for the slide icon click event. This toggles the slide menu.
         *
         * @method handleIconClick
         * @e {object} slide icon's click event
         */
        handleIconClick: function() {
            this._toggleSlide();
        },

        /**
         * Keyboard event handler for toggling support slide menu.
         *
         * @method handleSupportKey
         * @e {object} slide icon's click event
         * @slideObj {object} an instance of SlideMenu object.
         */
        handleSupportKey: function(e, slideObj) {
            if (slideObj) {
                slideObj._toggleSlide();
            }
        },

        /**
         * Closes the slide menu and hides it.
         *
         * @method hideSlider
         */
        hideSlider: function() {

            // disable the tab index of all the links in the support panel
            // when the panel is hidden.
            this._setSupportLinksTabIndex("-1");
            this.removeClass(this.slideContainer, this.slideToggleClass);
            this.removeClass(this.slideIcon, "active");
            this.slideIconLink.setAttribute("aria-expanded", "false");
        },

        /**
         * Opens the slide menu and shows it.
         *
         * @method showSlider
         */
        showSlider: function() {

            // enable the tab index of all the links in the support panel
            // when the panel is shown.
            this._setSupportLinksTabIndex("0");
            this.addClass(this.slideContainer, this.slideToggleClass);
            this.addClass(this.slideIcon, "active");
            this.slideIconLink.setAttribute("aria-expanded", "true");
        },

        /**
         * Sets the given tab index for all the links inside the slide panel.
         *
         * @method _setSupportLinksTabIndex ( private method )
         * @indexVal {string} the tab index value to set to.
         */
        _setSupportLinksTabIndex: function(indexVal) {
            var links = this.slidePanel.querySelectorAll("a");

            for (var i = 0; i < links.length; i++) {
                links[i].tabIndex = indexVal;
            }
        },

        /**
         * This method toggles the slide menu.
         *
         * @method _toggleSlide ( private method )
         */
        _toggleSlide: function() {
            if (this.hasClass(this.slideContainer, this.slideToggleClass)) {
                this.hideSlider();
            } else {
                this.showSlider();
            }
        },

        /**
         * Method that can be used to get all frames in the window.
         * If there are not any frames it will return the window
         * deriving its name from the PFILE parameter in the url.
         *
         * @method getAllFrames
         * @return {Array} returns array of frames in the current window
         */
        getAllFrames: function() {
            var frames = [];
            var windowParentFrames = window.parent.frames;
            for (var i = 0, len = windowParentFrames.length; i < len; i++) {
                frames.push(windowParentFrames[i]);
            }

            // Use the window to fill our frames array
            if (frames.length === 0 && window.frames.length === 0) {
                frames[0] = window;

                return frames;
            }

            return frames;
        }
    };

    // supportMenu is the object of type SlideMenu which is used to slide open the Support menu.
    var supportMenu = null;

    /**
     * Initializes all the instances for Slide Menus
     *
     * @method initializeSlideMenus
     */
    function initializeSlideMenus() {
        supportMenu = new SlideMenu("supportContainer");
        supportMenu.init();
    }

    window.addEventListener("content-container-init", initializeSlideMenus);

})(window);
Back to Directory File Manager