javascripthtmlfont-awesomejscolor

Borders of jscolor button not working after first click


When I click the green portion of this button, only the first click works. Every subsequent click after that doesn't work. I'll show you the hitbox below. (blue portion always works)enter image description here

My js code basically updates my sites text when choosing a color, but i can't figure out why the button fails after the first click.

I've tried using other fontawsome buttons and there was no change. I also used these buttons for other links and darkmode, so I think it's the way jscolor is integrating with fontawsome.

I'm using: jscolor/2.4.5/ font-awesome/5.15.4

Some of my HTML:

    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">



    <script src="https://cdnjs.cloudflare.com/ajax/libs/jscolor/2.4.5/jscolor.min.js"></script>


    <button class="theme-switch star-button"><i class="far fa-star"></i></button>

js:

document.addEventListener("DOMContentLoaded", function () {
    const starButtons = document.querySelectorAll('button.star-button');

    // Initialize jscolor picker
    jscolor.presets.default = {
        width: 200,
        position: 'right',
        backgroundColor: '#333',
        insetColor: '#FFF',
        shadow: true,
        borderRadius: 6,
        borderWidth: 1,
        borderColor: '#444',
        previewElement: null
    };

    function showColorPicker(e) {
        e.preventDefault();
        e.stopPropagation();
        const target = e.currentTarget.querySelector('i');
        const picker = new jscolor(target, {
            onFineChange: 'updateColor(this)',
            valueElement: null, // This ensures that the color value is not applied to the button itself
            previewElement: null, // No preview element
            styleElement: null // No style element
        });
        picker.show();
    }

    if (starButtons.length > 0) {
        starButtons.forEach(button => {
            button.addEventListener('click', showColorPicker);
            button.addEventListener('touchstart', showColorPicker); // Add touchstart event listener for mobile
            const greenPart = button.querySelector('.green-part');
            if (greenPart) {
                greenPart.addEventListener('click', handleGreenPartClick);
                greenPart.addEventListener('touchstart', handleGreenPartClick); // Add touchstart event listener for mobile
            }
            console.log('Star button event listener added');
        });
    } else {
        console.log('No star buttons found');
    }

    function handleGreenPartClick(e) {
        e.preventDefault();
        e.stopPropagation();
        alert('Green part clicked!');
    }

    // Apply the saved color on page load
    const savedColor = localStorage.getItem('selectedColor');
    if (savedColor) {
        const hslColor = JSON.parse(savedColor);
        applyColor(hslColor);
        console.log('Applied saved color:', hslColor);
    }
});

function updateColor(picker) {
    const hexColor = picker.toHEXString();
    const hslColor = hexToHSL(hexColor);

    console.log('New color selected: ', hslColor);

    applyColor(hslColor);
    // Save the selected color to localStorage
    localStorage.setItem('selectedColor', JSON.stringify(hslColor));
}

function applyColor(hslColor) {
    document.documentElement.style.setProperty('--clr-a-text', `hsl(${hslColor.h}, ${hslColor.s}%, var(--L-a-text))`);
    document.documentElement.style.setProperty('--clr-a-text-hvr', `hsl(${hslColor.h}, ${hslColor.s}%, calc(var(--L-a-text) * var(--L-a-text-hover-change)))`);
}

function hexToHSL(hex) {
    // Convert hex to RGB first
    let r = 0, g = 0, b = 0;
    if (hex.length === 7) {
        r = parseInt(hex.slice(1, 3), 16) / 255;
        g = parseInt(hex.slice(3, 5), 16) / 255;
        b = parseInt(hex.slice(5, 7), 16) / 255;
    }
    // Convert RGB to HSL
    let max = Math.max(r, g, b), min = Math.min(r, g, b);
    let h = 0, s = 0, l = (max + min) / 2;
    if (max !== min) {
        let d = max - min;
        s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
        switch (max) {
            case r: h = (g - b) / d + (g < b ? 6 : 0); break;
            case g: h = (b - r) / d + 2; break;
            case b: h = (r - g) / d + 4; break;
        }
        h /= 6;
    }
    return {
        h: Math.round(h * 360),
        s: Math.round(s * 100),
        l: Math.round(l * 100)
    };
}

Solution

  • The issue was with the re-instantiation of the Color Picker. This line specifically:

    const picker = new jscolor(target, {...}
    

    Updated Script:

        <script>
            document.addEventListener("DOMContentLoaded", function () {
                const starButtons = document.querySelectorAll('button.star-button');
    
                // Initialize jscolor picker
                let picker = null;
    
                jscolor.presets.default = {
                    width: 200,
                    position: 'right',
                    backgroundColor: '#333',
                    insetColor: '#FFF',
                    shadow: true,
                    borderRadius: 6,
                    borderWidth: 1,
                    borderColor: '#444',
                    previewElement: null
                };
    
                function showColorPicker(e) {
                    e.preventDefault();
                    e.stopPropagation();
                    const target = e.currentTarget.querySelector('i');
    
                    if(!picker){
                        picker = new jscolor(target, {
                            onFineChange: 'updateColor(this)',
                            valueElement: null, // This ensures that the color value is not applied to the button itself
                            previewElement: null, // No preview element
                            styleElement: null // No style element
                        });
    
                    }
    
                    if(picker) picker.show();
                }
    
                if (starButtons.length > 0) {
                    starButtons.forEach(button => {
                        button.addEventListener('click', showColorPicker);
                        button.addEventListener('touchstart', showColorPicker); // Add touchstart event listener for mobile
                        const greenPart = button.querySelector('.green-part');
                        if (greenPart) {
                            greenPart.addEventListener('click', handleGreenPartClick);
                            greenPart.addEventListener('touchstart', handleGreenPartClick); // Add touchstart event listener for mobile
                        }
                        console.log('Star button event listener added');
                    });
                } else {
                    console.log('No star buttons found');
                }
    
                function handleGreenPartClick(e) {
                    e.preventDefault();
                    e.stopPropagation();
                    alert('Green part clicked!');
                }
    
                // Apply the saved color on page load
                const savedColor = localStorage.getItem('selectedColor');
                if (savedColor) {
                    const hslColor = JSON.parse(savedColor);
                    applyColor(hslColor);
                    console.log('Applied saved color:', hslColor);
                }
            });
    
            function updateColor(picker) {
                const hexColor = picker.toHEXString();
                const hslColor = hexToHSL(hexColor);
    
                console.log('New color selected: ', hslColor);
    
                applyColor(hslColor);
                // Save the selected color to localStorage
                localStorage.setItem('selectedColor', JSON.stringify(hslColor));
            }
    
            function applyColor(hslColor) {
                document.documentElement.style.setProperty('--clr-a-text', `hsl(${hslColor.h}, ${hslColor.s}%, var(--L-a-text))`);
                document.documentElement.style.setProperty('--clr-a-text-hvr', `hsl(${hslColor.h}, ${hslColor.s}%, calc(var(--L-a-text) * var(--L-a-text-hover-change)))`);
            }
    
            function hexToHSL(hex) {
                // Convert hex to RGB first
                let r = 0, g = 0, b = 0;
                if (hex.length === 7) {
                    r = parseInt(hex.slice(1, 3), 16) / 255;
                    g = parseInt(hex.slice(3, 5), 16) / 255;
                    b = parseInt(hex.slice(5, 7), 16) / 255;
                }
                // Convert RGB to HSL
                let max = Math.max(r, g, b), min = Math.min(r, g, b);
                let h = 0, s = 0, l = (max + min) / 2;
                if (max !== min) {
                    let d = max - min;
                    s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
                    switch (max) {
                        case r: h = (g - b) / d + (g < b ? 6 : 0); break;
                        case g: h = (b - r) / d + 2; break;
                        case b: h = (r - g) / d + 4; break;
                    }
                    h /= 6;
                }
                return {
                    h: Math.round(h * 360),
                    s: Math.round(s * 100),
                    l: Math.round(l * 100)
                };
            }
        </script>