brainworxx/kreXX-TYPO3-Extension

View on GitHub
Resources/Public/JavaScript/Index.js

Summary

Maintainability
A
0 mins
Test Coverage
/**
 * kreXX: Krumo eXXtended
 *
 * kreXX is a debugging tool, which displays structured information
 * about any PHP object. It is a nice replacement for print_r() or var_dump()
 * which are used by a lot of PHP developers.
 *
 * kreXX is a fork of Krumo, which was originally written by:
 * Kaloyan K. Tsvetkov <kaloyan@kaloyan.info>
 *
 * @author
 *   brainworXX GmbH <info@brainworxx.de>
 *
 * @license
 *   http://opensource.org/licenses/LGPL-2.1
 *
 *   GNU Lesser General Public License Version 2.1
 *
 *   kreXX Copyright (C) 2014-2024 Brainworxx GmbH
 *
 *   This library is free software; you can redistribute it and/or modify it
 *   under the terms of the GNU Lesser General Public License as published by
 *   the Free Software Foundation; either version 2.1 of the License, or (at
 *   your option) any later version.
 *   This library is distributed in the hope that it will be useful, but WITHOUT
 *   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 *   FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
 *   for more details.
 *   You should have received a copy of the GNU Lesser General Public License
 *   along with this library; if not, write to the Free Software Foundation,
 *   Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

(function (TYPO3) {
    "use strict";

    /**
     * @namespace tabs
     */
    function tabs() {}

    /**
     * Initializing the tabs handling.
     *
     * @event DOMContentLoaded
     */
    tabs.onDocumentReady = function () {
        var elements = document.querySelectorAll('.nav-tabs li');

        for (var i = 0; i < elements.length; i++) {
            elements[i].addEventListener('click', tabs.toggle);
        }
    };

    /**
     * Toggle the tab on click.
     *
     * @event click
     * @param {Event} event
     */
    tabs.toggle = function (event) {
        var activeTab = document.querySelector('.nav-tabs li.active');
        var activeContent = document.querySelector('.tab-content .tab-pane.active');

        if (activeTab !== null) {
            activeTab.classList.remove('active');
        }

        if (activeContent !== null) {
            activeContent.classList.remove('active');
        }

        var li = event.target.parentNode;

        if (li !== null) {
            li.classList.add('active');
            document.getElementById(li.getAttribute('data-tab')).classList.add('active');
        }
    };

    /**
     * @namespace formSupport
     */
    function formSupport(){}

    /**
     * Initializing the form support.
     *
     * @event DOMContentLoaded
     */
    formSupport.onDocumentReady = function () {
        var checkboxes = document.querySelectorAll('[id^="factory."]');

        for (var i = 0, n = checkboxes.length; i < n; i++) {
            formSupport.toggle(checkboxes[i]);
            checkboxes[i].addEventListener('click', function () {
                formSupport.toggle(this);
            }, true);
        }


        document.getElementById('main-save').addEventListener('click', function () {
            var form = document.getElementById('save-form');
            if (typeof form === 'object' && form !== 'undefined' && form != null) {
                form.submit();
            }
        }, true);

        document.getElementById('mode-switch').addEventListener('change', formSupport.changeMode);

        document.getElementById('clear-cookies').addEventListener('click', function () {
            // We do not delete the cookie, we simply remove all settings in it.
            /** @type {Object} */
            var settings = {};
            /** @type {Date} */
            var date = new Date();
            date.setTime(date.getTime() + (99 * 24 * 60 * 60 * 1000));
            /** @type {string} */
            var expires = 'expires=' + date.toUTCString();
            document.cookie = 'KrexxDebugSettings=' + JSON.stringify(settings) + '; ' + expires + '; path=/';

            ajaxRefresh.message({
                class: 'success',
                text: 'All cookie settings were removed!'
            })
        }, true);
    };

    /**
     * When activating the checkbox behind the form element, we deactivat the
     * form element, belonging to the checkbox.
     *
     * @param {HTMLInputElement} checkbox
     */
    formSupport.toggle = function (checkbox) {
        // Find the corresponding element.
        var id = checkbox.id.split('.');
        if (typeof id[1] !== 'undefined') {
            var element = document.getElementById(id[1]);
            var fallback = document.getElementById(id[1] + '-fallback');
        }

        if (typeof element === 'object' && typeof element !== 'undefined' && element != null) {
            if (checkbox.checked) {
                element.disabled = true;
                element.parentNode.classList.remove('active');
                fallback.classList.remove('disabled');
            } else {
                element.parentNode.classList.add('active');
                element.disabled = false;
                fallback.classList.add('disabled');
            }
        }
    };

    /**
     * We simply set a class on the higher dom elements to show the expert settings, if desired.
     *
     * @param {Event} event
     */
    formSupport.changeMode = function (event) {
        var modeSwitch = document.getElementById('mode-switch');
        var value = modeSwitch.options[modeSwitch.selectedIndex].value;

        if (value === 'expert') {
            document.getElementById('tabpanel').classList.add('expert-mode');
        } else {
            document.getElementById('tabpanel').classList.remove('expert-mode');
        }
    };

    /**
     * The ajax related stuff.
     *
     * @namespace ajaxRefresh
     */
    function ajaxRefresh() {}

    /**
     * The ajax translation texts.
     *
     * @type {{}}
     */
    ajaxRefresh.ajaxTranslate = {}

    /**
     * Initializing the ajax handling
     *
     * @event DOMContentLoaded
     */
    ajaxRefresh.onDocumentReady = function () {
        // Read the translation texts.
        ajaxRefresh.ajaxTranslate = window.ajaxTranslate;

        // Get a first impression.
        ajaxRefresh.call();

        // Fetch a new list every 5 seconds.
        ajaxRefresh.timeout();

        // Register the bubbelung eventhandler for the delete button.
        document.querySelector('table.krexx-logs').addEventListener('click', ajaxRefresh.deleteHandling);
    };

    /**
     * Timeout method for refreshing the logfile list.
     */
    ajaxRefresh.timeout = function () {
        setTimeout(function () {
            ajaxRefresh.call();
            ajaxRefresh.timeout();
        }, 5000);
    };

    /**
     * We store the last answer, to check if there was an update.
     *
     * @type {string}
     */
    ajaxRefresh.lastAnswer = '';

    /**
     * Refresh the logfile list.
     */
    ajaxRefresh.call = function () {
        var request = new XMLHttpRequest();
        request.open("GET", TYPO3.settings.ajaxUrls['includekrexx_refresh'], true);

        var table = document.querySelector('table.krexx-logs tbody');
        request.onload = function (event) {
            var result = JSON.parse(request.responseText);

            // Are there any logiles, at all?
            if (result.length === 0) {
                document.querySelector('#tab-1 .table-wrapper').classList.add('display-none');
                document.querySelector('#tab-1 .noresult').classList.remove('display-none');
                // Nothing more to do here.
                return;
            }

            document.querySelector('#tab-1 .table-wrapper').classList.remove('display-none');
            document.querySelector('#tab-1 .noresult').classList.add('display-none');

            var html = ajaxRefresh.generateHtml(result);

            if (ajaxRefresh.lastAnswer !== html) {
                table.innerHTML = html;
                ajaxRefresh.message({
                    text: ajaxRefresh.ajaxTranslate.updatedLoglist,
                    class: 'success'
                });
            }

            ajaxRefresh.lastAnswer = html;

        };

        request.send();
    };

    /**
     * Generate the HTML for the file list.
     *
     * @param result
     * @return {string}
     */
    ajaxRefresh.generateHtml = function (result) {
        var html = '';
        var i;

        for (var key in result) {
            if (!result.hasOwnProperty(key)) {
                continue;
            }

            var file = result[key];
            html += '<tr ' + ajaxRefresh.generateBackgroundStyle(file.name) + '>';
            html += '<td><a target="_blank" href="' + file.dispatcher + '">  ' + file.name + '</a></td><td class="meta">';
            for (i = 0; i < file.meta.length; i++) {
                html += '<div class="krexx-data-wrapper"><div class="krexx-icon-wrapper"><div class="krexx-icon ' + file.meta[i].level + '" title="' + file.meta[i].level + '"></div></div><div class="krexx-data">';
                html += '<b>' + file.meta[i].type + '</b><br />';
                html += ajaxRefresh.ajaxTranslate.in + ' ' + file.meta[i].filename + ', ' + ajaxRefresh.ajaxTranslate.line + ' ' + file.meta[i].line;
                html += '</div></div>'
            }
            if (file.meta.length > 0) {
                html += '<div class="krexx-spacer"></div>'
            }
            html += '</td>';

            html += '<td class="time">' + file.time + '</td><td class="size">' + file.size + '</td>';
            html += '<td><div class="button delete" data-id="' + file.id + '"></div></td></tr>';
        }

        return html;
    };

    /**
     * Generate the background style from the time string.
     *
     * @param string string
     *
     * @return string
     *   style=" background-color: rgba(255, 0, 0, 0.1);"
     */
    ajaxRefresh.generateBackgroundStyle = function (string) {
        var chr, hash, i, values;

        for (i = 0; i < string.length; i++) {
            chr   = string.charCodeAt(i);
            hash  = ((hash << 5) - hash) + chr;
            // Convert to 32bit integer
            hash |= 0;
        }

        values = Math.abs(hash).toString().match(/.{1,2}/g);

        return 'style=" background-color: rgba(' + values[3] + ', ' + values[2] + ', ' + values[1] + ', 0.2' + values[0] + ');"';
    };

    /**
     * Delete click handler for the delete list.
     *
     * @param event
     */
    ajaxRefresh.deleteHandling = function (event) {
        var target = event.target;
        var id;

        // Retrieve the id.
        if (target.hasAttribute('data-id')) {
            id = target.getAttribute('data-id')
        } else if (target.parentElement.hasAttribute('data-id')) {
            id = target.parentElement.getAttribute('data-id')
        }

        // Found anything?
        if (typeof id === 'undefined' || id === null) {
            // No id found. Early return.
            return;
        }

        var confirmed = confirm(ajaxRefresh.ajaxTranslate.deletefile);

        if (confirmed === false) {
            return;
        }

        var request = new XMLHttpRequest();
        request.open("GET", TYPO3.settings.ajaxUrls['includekrexx_delete'] + '&fileid=' + id, true);

        request.onload = function (event) {
            try {
                ajaxRefresh.message(JSON.parse(request.responseText));
            } catch (e) {
                // We are not going to output the answer from the server, although
                // it is visible in the browser inspector.
                ajaxRefresh.message({class: 'error', text: ajaxRefresh.ajaxTranslate.error});
            }

            ajaxRefresh.call();
        };

        request.send();
    };

    /**
     * Ajax related messaging.
     *
     * @param {{}} json
     */
    ajaxRefresh.message = function (json) {
        var messagebox = document.querySelector('.message-container-outer');
        var message = document.createElement("div");

        message.classList.add('ajax-msg');
        message.classList.add(json.class);
        message.innerHTML = '<div class="icon"></div><div class="text">' + json.text + '</div>';
        messagebox.appendChild(message);

        setTimeout(function () {
            message.classList.add('fade');
            setTimeout(function () {
                message.classList.add('remove');
                setTimeout(function () {
                    messagebox.removeChild(message);
                }, 600);
            }, 600);
        }, 4000);
    }

    if (document.readyState !== 'loading') {
        tabs.onDocumentReady();
        formSupport.onDocumentReady();
        ajaxRefresh.onDocumentReady();
    } else {
        // @deprecated
        // Will be removed as soon as we drop TYPO3 11 support.
        document.addEventListener("DOMContentLoaded", function () {
            tabs.onDocumentReady();
            formSupport.onDocumentReady();
            ajaxRefresh.onDocumentReady();
        });
    }

})(TYPO3);