HEX
Server: Microsoft-IIS/8.5
System: Windows NT YDAWBH120 6.3 build 9600 (Windows Server 2012 R2 Standard Edition) AMD64
User: tentjecom_web (0)
PHP: 7.4.14
Disabled: NONE
Upload Files
File: D:/HostingSpaces/pietvanmierlo/stempelbv.nl/resources/js/kms/attributes/componentAreaCopier.js
/**
 * Knows how to copy component area data to other component areas
 */
class ComponentAreaCopier {
    constructor()
    {
        let self = this;

        this._componentAreaManagers = []; //An array of componentAreaManagers

        this._registerButtonClickListenersDebounced = this.debounce(function () {
            self._registerButtonClickListeners();
        }, 50);
    }

    /**
     * Copy the contents of one component area to another one
     *
     * @param {ComponentAreaManager} fromComponentAreaManager
     * @param {ComponentAreaManager} toComponentAreaManager
     * @private
     */
    _copy(fromComponentAreaManager, toComponentAreaManager)
    {
        //Get the component area savestate which contains all source info we need to have to make the copy possible
        let saveState = fromComponentAreaManager.getComponentAreaSaveState();
        //Copy it by giving the destination component area manager the save state
        toComponentAreaManager.addNewComponentsBasedOnComponentAreaSaveState(saveState)
    }

    /**
     * Make the componentAreaCopier aware of a component area manager
     * So that other componentAreaManagers can be copied to it.
     *
     * @param {ComponentAreaManager} componentAreaManager
     */
    registerComponentAreaManager(componentAreaManager)
    {
        if(!(componentAreaManager instanceof ComponentAreaManager)) {
            console.error('ComponentAreaCopier: Could not register a component area manager since that was not an instance of ComponentAreaManager. Was:', componentAreaManager);
            return;
        }

        this._componentAreaManagers.push(componentAreaManager);

        this._registerButtonClickListenersDebounced();
    }

    /**
     * Registers click event listeners on the component area's copy buttons.
     *
     * @private
     */
    _registerButtonClickListeners()
    {
        let self = this;
        this._componentAreaManagers.forEach(
            /** @param {ComponentAreaManager} componentAreaManager **/
            function(componentAreaManager) {
                //Find the copy button in the component area
                let selector = '.js-component-area-button';
                let button = componentAreaManager.getWrapperElement().querySelector(selector);
                if(!button) {
                    console.error('ComponentAreaCopier: Could not find the copy button in the following componentAreaManager using this selector "'+selector+'": ', componentAreaManager);
                    return;
                }

                //The confirmation controller handles the onClick on the copy button, But only when the user confirms the action. When he confirms the action, we trigger the _onClick method
                new ConfirmationController(button).setConfirmCallback((function(componentAreaManager) {
                    return function() {
                        self._onClick(componentAreaManager);
                    }
                }(componentAreaManager)));
            }
        );
    }

    /**
     * Triggered when the user clicked the copy button and confirmed the copy
     *
     * {ComponentAreaManager} componentAreaManager
     * @private
     */
    _onClick(componentAreaManager) {
        //Find the select in the component area
        let selector = '.js-component-area-select';
        let select = componentAreaManager.getWrapperElement().querySelector(selector);
        if(!select) {
            console.error('ComponentAreaCopier: Could not find the select in the following componentAreaManager using this selector "'+selector+'": ', componentAreaManager);
            return;
        }

        //Get the destination component area manager. Or display an error when we don't find it.
        let toComponentAreaManager = this._findComponentAreaManagerByWrapperId(select.value);
        if(!toComponentAreaManager) {
            console.error('componentAreaCopier: could not copy the structure of '+componentAreaManager.getWrapperElement().id+' to '+select.value);
            return
        }

        //Make the copy
        this._copy(componentAreaManager, toComponentAreaManager);

        //Determine if we need to change to another tab. If so, change to that tab
        let selectedOption = select.children[select.selectedIndex];
        if(selectedOption && 'tab' in selectedOption.dataset) {
            let tabToChangeTo = selectedOption.dataset.tab;
            window.location.hash = '#'+tabToChangeTo; //Change to that tab.
        }

        //Disable all copy notifications. Event outside the component area managers we managae
        document.querySelectorAll('.js-component-area-confirmation').forEach(function(confirmationTextElement) {
            confirmationTextElement.classList.remove('active')
        });

        //Show the copy confirmation in the the destination component area manager wrapper.
        let notification = toComponentAreaManager.getWrapperElement().querySelector('.js-component-area-confirmation');
        notification.classList.add('active');
    }

    /**
     * @param id
     * @private
     * @return {ComponentAreaManager|null}
     */
    _findComponentAreaManagerByWrapperId(id)
    {
        let componentAreaManagersCount = this._componentAreaManagers.length;
        for(let index = 0; index < componentAreaManagersCount; index++) {
            /** @param {ComponentAreaManager} componentAreaManager **/
            let componentAreaManager = this._componentAreaManagers[index];

            if(id === componentAreaManager.getWrapperElement().id)
                return componentAreaManager;
        }


        return null;
    }

    /**
     * Triggers the function after the wait time (milliseconds) has expired and only
     * if the function is not triggered again before the wait time expired.
     *
     * @param func
     * @param wait
     * @param immediate
     * @returns {Function}
     */
    debounce(func, wait, immediate) {
        let timeout;

        return function() {
            let context = this, args = arguments;
            let later = function() {
                timeout = null;
                if (!immediate) func.apply(context, args);
            };
            let callNow = immediate && !timeout;
            clearTimeout(timeout);
            timeout = setTimeout(later, wait);
            if (callNow) func.apply(context, args);
        };
    };
}