Color wheel in notification/popup

Hello,
currently I'm using this code in a template_ui node to create a color selector on my dashboard. This is working fine so far.

But I don't want it to be shown permanently on the dashboard, but rather in a browser popup, when triggered.
My first idea was to inject the hole code into a notification with " Accept raw HTML/JavaScript input..." activated. Sadly this doesn't worked. (Could have been so easy ;))

Example:

[{"id":"e237defc.5d472","type":"template","z":"7510731b.b51ddc","name":"","field":"payload","fieldType":"msg","format":"html","syntax":"plain","template":"<script src=\"/iro.min.js\"></script>\n<script>\n    var theScope = scope;\n    var storedStateColor = getLastColor(theScope);\n    var colorPicker;\n    function initIroJs(){if(typeof(iro) === 'object'){colorPicker = new iro.ColorPicker(\"#color-picker-container\",{width: 300,color: storedStateColor,layout: [{component: iro.ui.Wheel,},]});colorPicker.on('input:end', onColorChange);}else{setTimeout(function() { initIroJs(); }, 250);}}\n    function onColorChange(){theScope.send({ payload: colorPicker.color.rgb });}function messageReceived(payload){if(typeof(colorPicker) === 'object'){colorPicker.color.rgb = payload;}}\n    function getLastColor(theScope){if(typeof(theScope.msg) === 'object'){if(typeof(theScope.msg.payload) === 'object' &&theScope.msg.payload.match(/r:/)){return theScope.msg.payload;}}return 'rgb(255, 255, 0)';}\n    theScope.$watch('msg.payload', messageReceived);\n    initIroJs();\n</script>\n<div id=\"color-picker-container\" style=\"min-height: 350px;\"></div>","output":"str","x":420,"y":520,"wires":[["77e8efa1.ae8f7"]]},{"id":"29bdc443.b3722c","type":"inject","z":"7510731b.b51ddc","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"true","payloadType":"bool","x":270,"y":520,"wires":[["e237defc.5d472"]]},{"id":"77e8efa1.ae8f7","type":"ui_toast","z":"7510731b.b51ddc","position":"dialog","displayTime":"3","highlight":"","sendall":true,"outputs":1,"ok":"OK","cancel":"","raw":true,"topic":"","name":"","x":610,"y":520,"wires":[[]]}]

Do you have any suggestions to get this work?
Thanks

hi aterus,

maybe this code fits your needs:

<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')
        {
            if($('#color-picker-container').length === 0)
            {
                $('<div></div>')
                    .prop('id', 'color-picker-modal')
                    .css({
                        'background-color': 'rgba(0,0,0,0.3)',
                        'z-index': 999,
                        width: '100%',
                        height: '100%',
                        position: 'absolute',
                        left: 0,
                        top: 0,
                    })
                    .on('click', toggleColorWheelDisplay)
                    .hide()
                    .appendTo('body:first')
                ;
                $('<div></div>')
                    .prop('id', 'color-picker-container')
                    .css({
                        height: 350,
                        position: 'absolute',
                        'z-index': 1000,
                        'background-color': 'pink',
                        padding: '15px',
                        'border-radius': '5px',
                    })
                    .hide()
                    .appendTo('body:first')
                ;
            }
            
            //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';
    }
    
    function toggleColorWheelDisplay(e)
    {
        let isVisible = $('#color-picker-container:visible').length > 0 ? true : false;
        if(isVisible)
        {
            $('#color-picker-modal').hide();
            $('#color-picker-container').hide();
        }
        else 
        {
            let offset = $(this).offset();
            offset.top += $(this).height();
            
            $('#color-picker-modal').show();
            $('#color-picker-container').show().offset(offset);
        }
    }
    
    theScope.$watch('msg.payload', messageReceived); //listen for incoming messages
    initIroJs();
    $('.toggleColorWheel').on('click', toggleColorWheelDisplay);
</script>
<div class="toggleColorWheel">show color picker</div>

this are only some quick changes to my original version. it still is only able to handle a single instance of the color wheel and it is a bit ugly, so you might want to change some bits :slight_smile:

2 Likes