JavaScript is required
Ga naar de inhoud

21 juni 2021

Front-end Code Voorbeeld

/**
 *
 * @param {string} type: id, class or body
 * @param {string} value: element name
 *
 */

const element = function (type, value) {
        switch (type) {
            case 'id':
                return document.getElementById(value);
            case 'class':
                return document.getElementsByClassName(value);
            case 'tag':
                return document.getElementsByTagName(value);
            case 'body':
                return document.body;
        }
        return null;
    };

/**
 *
 *  @param {object} colors: Object with color data
 *  Builds menu of color choices based on color object
 *  Inserts <li> items into the existing <ul> DOM element
 *  Adds classes to <head> section dynamically
 *
 */

const menuChoices = element('id', 'choices');

const buildColorMenu = function (colors) {
    let classes = '';
    colors.forEach(function (color, index) {

        // build listItem with radio button, label and keyCode hint
        let listItem = document.createElement('li');
        listItem.setAttribute('id', color.label);
        listItem.setAttribute('class', color.label);
        menuChoices.appendChild(listItem);

        let radioElement = document.createElement('input');
        radioElement.setAttribute('type', 'radio');
        radioElement.setAttribute('id', color.label + 'btn');
        radioElement.setAttribute('name', 'color');
        radioElement.setAttribute('value', color.value);
        listItem.appendChild(radioElement);

        listItem.innerHTML += color.label;

        let spanElement = document.createElement('span');
        spanElement.innerHTML = index + 1;
        listItem.appendChild(spanElement);

        classes += '.' + color.label + ' { background-color: ' + color.value + ' }\n';
    });

    // build Stylesheet with classes
    const stylesheet = document.createElement('style');
    stylesheet.setAttribute('type', 'text/css');
    stylesheet.setAttribute('rel', 'stylesheet');
    stylesheet.innerHTML = classes;
    const head = element('tag', 'head')[0];
    head.appendChild(stylesheet);
};

/**
 *
 *  Prevents color transition effect on background from firing
 *  after page load
 *
 */

const initBackgroundTransition = function () {
    if (bodyTag.classList.contains('transition') === false) {
        bodyTag.classList.add('transition');
    }
};

/**
 *
 *  @param {boolean} display: Show or hide the color menu
 *
 */

const menuIcon = element('class', 'icon');
const menuToggler = element('id', 'toggler');
const menuColors = element('id', 'colors');

const toggleColorMenu = function (display) {
    if (display === true) {
        menuColors.classList.add('display');
    } else {
        menuColors.classList.remove('display');
    }
};

/**
 *
 *  Sets the mouseover and mouseout eventListener
 *
 */

const setTogglerEvents = function () {
    menuToggler.addEventListener('mouseover', function () {
        toggleColorMenu(true);
        initBackgroundTransition();
    });
    menuToggler.addEventListener('mouseout', function () {
        toggleColorMenu(false);
    });
    menuColors.addEventListener('mouseover', function () {
        toggleColorMenu(true);
    });
};

/**
 *
 *  @param {string} color: Color to ly to the body background
 *  Uses a variable to store the previous applied color className
 *
 */

let previousColorClass = null;
const bodyTag = element('body');

const changeBackgroundColor = function (color) {
    if (previousColorClass !== null) {
        bodyTag.classList.remove(previousColorClass);
    }
    bodyTag.classList.add(color);
    previousColorClass = color;
};

/**
 *
 *  @param {string} label: Label for the selected color
 *  @param {string} value: Color value for the selected color
 */

const bodyMessage = element('id', 'message');

const changeBodyMessage = function (label, value) {
    bodyMessage.innerHTML = label;

    const addNewLine = document.createElement('br');
    bodyMessage.appendChild(addNewLine);

    const showColorValue = document.createElement('span');
    showColorValue.setAttribute('class', 'light');
    bodyMessage.appendChild(showColorValue);
    showColorValue.innerHTML += value;
};

/**
 *
 *  @param {string} button: Radio button checked example from source #1
 *
 */

const selectRadioButton = function (button) {
    document.getElementById(button).checked = true;
};

/**
 *
 *  @param {object} colors: Object with color data
 *  @param {number} count: Number of colors
 *  Sets click eventListener on <li> element for all menu choices
 *
 */

const setColorChoiceEventsLoop = function (colors) {
    colors.forEach(function (color, index) {
        setColorChoiceEvents(color, index + 1);
    });
};

/**
 *
 *  @param {string} color: Sets click eventListener on one <li> element
 *  @param {object} colors: Object with color data
 *
 */

const setColorChoiceEvents = function (color, index) {
    document.getElementById(color.label).addEventListener('click', function () {
        changeBackgroundColor(color.label);
        selectRadioButton(color.label + 'btn');
        changeBodyMessage(color.label, color.value);
        toggleColorMenu(false);
    });
};

/**
 *
 *  Sets click eventListener on <body> to close color menu
 *
 */

const setCloseMenuFromBodyEvent = function () {
    bodyTag.addEventListener('click', function () {
        toggleColorMenu(false);
    });
};

/**
 *
 * @param {object} colors: Object with color data
 *  keyCode for numeric key 1 through 9; example from source #2
 *
 */

const setKeyPressEvent = function (colors) {
    bodyTag.addEventListener('keypress', function (pressed) {
        if (pressed.keyCode >= 49 && pressed.keyCode <= 57) {
            changeBackgroundKeyPress(pressed.key - 1, colors);
        }
    });
};

/**
 *
 *  @param {number} key: Change menu and body background color
 *                       based on numeric keys 1 through 9
 *  @param {object} colors: Object with color data
 *
 */

const changeBackgroundKeyPress = function (key, colors) {
    const color = colors[key];
    initBackgroundTransition();
    changeBackgroundColor(color.label);
    selectRadioButton(color.label + 'btn');
    changeBodyMessage(color.label, color.value);
};

/**
 *
 *  Thought behind colors object is to make the color menu dynamic
 *  and generate the HTML for the choices using JavaScript. The keyCode
 *  works for the first 9 colors. A stylesheet is added to the <head>
 *  tag to avoid the use of document.body.style
 *
 */

const colors = [
    {label: 'home', value: '#999999'},
    {label: 'red', value: '#CC2929'},
    {label: 'orange', value: '#FF8000'},
    {label: 'purple', value: '#9C3DCC'},
    {label: 'green', value: '#3DCC3D'},

    // uncomment for additional colors
    {label: 'yellow', value: '#FFD500'},
    {label: 'aqua', value: '#29CCCC'},
    {label: 'blue', value: '#295FCC'},
    {label: 'magenta', value: '#E64595'}
];

/**
 *
 *  Initialize the color toggle menu, choices and eventListeners
 *
 */

const initColorMenu = () => {
    buildColorMenu(colors);
    setTogglerEvents();
    setColorChoiceEventsLoop(colors);
    setCloseMenuFromBodyEvent();
    setKeyPressEvent(colors);
    toggleColorMenu(false);
};

initColorMenu();

/**
 *
 *  Sources
 *
 *  #1: https://stackoverflow.com/questions/21166860/check-a-radio-button-with-javascript
 *  #2: https://stackoverflow.com/questions/13196945/keycode-values-for-numeric-keypad/13196983
 *
 */

Laatst bijgewerkt: 12 december 2024