Dashboard Colour Wheel

as i recently switched my home automation from mysensors to node red (and node red dashboard), i stumbled over this thread. as i have implemented iro.js in mysensors as a component previously, i wanted to use this library on my new dashboard as well.

as this was the first thread listed in googles search results, i wanted to share my solution, for those of you who are not satisfied with the default color picker node.

i added a "template" node to my flow, unticked "Pass through messages from input" and wrote the following code into it.

beware: you need to change some bits, if you want to use multiple instances of this on your dashboard.

<script src="https://cdn.jsdelivr.net/npm/@jaames/iro/dist/iro.min.js"></script>
<script>
    var theScope = scope;
    var storedStateColor = getLastColor(theScope);
    var colorPicker;
    
    /**
     * initialize iro.js component
     */
    function initIroJs()
    {
        //wait for iro library to be loaded
        if(typeof(iro) === 'object')
        {
            //and initialize component
            colorPicker = new iro.ColorPicker(
                "#color-picker-container",
                {
                    width: 300,
                    color: fixColorString(storedStateColor),
                }
            );
            
            colorPicker.on('input:change', onColorChange);
        }
        else
        {
            setTimeout(function() { initIroJs(); }, 250);
        }
    }
    
    function onColorChange()
    {
        theScope.send({ payload: colorPicker.color.hexString });
    }
    
    /**
     * update colorPicker state if msg.payload is received
     * 
     * @param {string} payload - hex color string
     */
    function messageReceived(payload)
    {
        if(typeof(colorPicker) === 'object')
        {
            colorPicker.color.hexString = fixColorString(payload);
        }
    }
    
    /**
     * prefix hex color strings with # if not present
     * 
     * @param {string} color - hex color string
     */
    function fixColorString(color)
    {
        return color.startsWith('#') ? color : '#' + color;
    }
    
    /**
     * checks for stored msg object and returns the last set color, if present
     * 
     * @param {object} theScope
     */
    function getLastColor(theScope)
    {
        //check if stored state has a msg object
        if(typeof(theScope.msg) === 'object')
        {
            //check if payload is a hex color string
            if(typeof(theScope.msg.payload) === 'string' &&
               theScope.msg.payload.match(/^#?[A-Fa-f0-9]{6}$/))
            {
                return theScope.msg.payload;
            }
        }
        
        return '#000000';
    }
    
    theScope.$watch('msg.payload', messageReceived); //listen for incoming messages
    initIroJs();
</script>
<div id="color-picker-container" style="min-height: 350px;"></div>

i am currently learning how to make this a completely functional and publishable node.

3 Likes