I think the solution is within css inheritance or possibly the use of tranparent ?
There are a few LED nodes available...you could just use them, or dig into their code to see what tricks, if any, they use.
And some random flow... (EDIT - probably what we have been playing with all along )
https://flows.nodered.org/flow/1538793825685bd8f08e4aea16ca2c74
Found something about a function call 'ui.isDark()' but I do not know how to use it in a function node.
ui.isDark()
can't be reached at the end-user position. So no help from that.
Dashboard theme is not dynamic thing so I really cant see the point of creating dynamic color solution. Except if you really have created CSS overrides for dashboard with dynamic color choice involved - that will be nice thing to see. There is a lot of obstacles on the way. Quite of challenge.
Hi @hotNipi, thank you for your view point it is much appreciated.
My aim with colour is for the led array to simply look ok under dark or light theme, not to change on the fly.
Are you saying that a function node cannot access ui.isDark() ?
If so then can a function node read a named dashboard colour and use that to guess which theme is in operation ?
You can ask the color of the body element inside ui_template
node
<script>
var themedBackgroundColor = window.getComputedStyle(document.body, null).getPropertyValue('background-color')
console.log(themedBackgroundColor)
// or with jquery
// var themedBackgroundColor = $('body').css('background-color')
</script>
That will probably be enough. My dashboard template only fails on the way it looks when trying to show an led that is off.
This is ok for dark
But not so good for light
The problem I have now is rewriting
<span class="led-squarex" style="background-color: {{msg.bank2[$index]}}; box-shadow: black 0 -1px 1px 0px, inset black 0 -1px 4px, {{msg.bank2[$index]}} 0 3px 3px;"></span>
for the light theme using these colours
:root {
--nr-dashboard-pageBackgroundColor: #fafafa;
--nr-dashboard-pageTitlebarBackgroundColor: #0094CE;
--nr-dashboard-groupTextColor: #1bbfff;
--nr-dashboard-groupBackgroundColor: #ffffff;
--nr-dashboard-groupBorderColor: #ffffff;
--nr-dashboard-widgetTextColor: #111111;
--nr-dashboard-widgetBackgroundColor: #0094ce;
--nr-dashboard-widgetBorderColor: #ffffff;
--nr-dashboard-widgetColor: #0094ce;
--nr-dashboard-widgetBgndColor: #ffffff;
}
To determine is the background color dark or light there is many examples in world wide, pointing out first one - Determine If A Color Is Bright Or Dark Using JavaScript - Andreas Wik
Also if you have predefined colors as you are using them with input, why not to make classes for colors and send name of class and then add that class to each led. Then if you determine dark or light background, use proper class for "led off" based on that knowledge
Sound like a very good idea but I am not sure of the detail. Currently I just send two banks of colour arrays, msg.bank1["#ff0000", ...] and msg.bank2[...].
How do I send the colour class, would it be a text variable and what does the css and html look like, starting from this ?
<style>
.led-squarex {
overflow: hidden;
float: right;
padding: 0px;
width: 8px;
height: 20px;
margin: 0px 2px 0px 0px;
border-radius: 0%;
}
</style>
<div style="width: 98.5%; flex: 1; overflow: hidden; position: absolute; top: 3px; left: 6px; padding: 0px;">{{msg.title1}}
<div style="min-width: 0; position: relative; float:right; padding-right: 7px;">
<span ng-repeat="led in msg.bank1 track by $index" style="position: relative; float: right;">
<span class="led-squarex" style="background-color: {{msg.bank1[$index]}}; box-shadow: #ffffff 0 -1px 1px 0px, inset black 0 -1px 4px, {{msg.bank1[$index]}} 0 3px 3px;"></span>
</span>
</div>
</div>
<div style="width: 98.5%; flex: 1; overflow: hidden; position: absolute; top: 27px; left: 6px; padding: 0px;">{{msg.title2}}
<div style="min-width: 0; position: relative; float:right; padding-right: 7px;">
<span ng-repeat="led in msg.bank2 track by $index" style="position: relative; float: right;">
<span class="led-squarex" style="background-color: {{msg.bank2[$index]}}; box-shadow: black 0 -1px 1px 0px, inset black 0 -1px 4px, {{msg.bank2[$index]}} 0 3px 3px;"></span>
</span>
</div>
</div>
P.S. I suspect I have some redundant css here.
PPS In an attempt to reduce the msg size I had an earlier design where I only sent an led id and its colour but the dashboard template code seemed to mushroom in size and complexity. Is there a general rule for such dilemmas ?
Made a little and very incomplete example of how it may be done.
[{"id":"ee7c5ee7.d5c75","type":"ui_template","z":"c93ec0f3.64b248","group":"621f3245.59d80c","name":"","order":1,"width":0,"height":0,"format":"<div id=\"{{'title_'+$id}}\" style=\"overflow: hidden; position: absolute; top: 3px; left: 6px; padding: 0px;\"></div>\n<div id=\"{{'bar_'+$id}}\" style=\"min-width: 0; position: relative; float:right;\"></div>\n\n<script>\n(function(scope) {\n //var tbg = $('body').css('background-color')\n // missing functionality - determine is the color dark or light \n \n // suffix for \"off led\" can be -dark or -light. Will be applied to \"off\" \n var suffix = \"-dark\"\n scope.$watch('msg', function(msg) {\n if (msg) {\n // Do something when msg arrives\n // change title\n $(\"#title_\"+scope.$id).text(msg.title1);\n //clear bar\n $(\"#bar_\"+scope.$id).empty()\n // find and replace \"off\" color to change it to be off-dark or off-light\n var colorClasses = msg.bank1.map(item => item === \"off\" ? \"off\"+suffix : item);\n // create new span elements and add them to the bar element\n colorClasses.forEach(cl => {\n $('<span/>', {'class': 'led-squarex '+cl}).appendTo(\"#bar_\"+scope.$id);\n })\n \n \n }\n });\n})(scope);\n</script>\n","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":true,"templateScope":"local","x":560,"y":700,"wires":[[]]},{"id":"3c6715e7.fce5da","type":"inject","z":"c93ec0f3.64b248","name":"","props":[{"p":"bank1","v":"[\"yellow\",\"green\",\"red\",\"off\"]","vt":"json"},{"p":"title1","v":"Led bar","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","x":410,"y":700,"wires":[["ee7c5ee7.d5c75"]]},{"id":"e63bf4e4.62e018","type":"ui_template","z":"c93ec0f3.64b248","group":"621f3245.59d80c","name":"leds css","order":5,"width":0,"height":0,"format":"<style>\n.led-squarex {\n overflow: hidden;\n float: right;\n padding: 0px;\n width: 8px;\n height: 20px;\n margin: 0px 2px 0px 0px;\n border-radius: 0%;\n\n}\n.yellow{\n background-color:yellow;\n box-shadow: #000 0 -1px 6px 1px, inset yellow 0 -1px 8px, yellow 0 3px 11px;\n}\n.green{\n background-color:green;\n box-shadow: #000 0 -1px 6px 1px, inset green 0 -1px 8px, green 0 3px 11px;\n}\n.red{\n background-color:red;\n box-shadow: #000 0 -1px 6px 1px, inset red 0 -1px 8px, red 0 3px 11px;\n}\n.off-dark{\n background-color:#cfcfcf;\n box-shadow: #000 0 -1px 6px 1px, inset black 0 -1px 8px, black 0 3px 11px;\n}\n.off-light{\n background-color:gray;\n box-shadow: #000 0 -1px 6px 1px, inset gray 0 -1px 8px, gray 0 3px 11px;\n}\n</style>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":true,"templateScope":"global","x":560,"y":660,"wires":[[]]},{"id":"621f3245.59d80c","type":"ui_group","name":"State 1","tab":"39f46c04.da4d54","order":1,"disp":true,"width":"6","collapse":false},{"id":"39f46c04.da4d54","type":"ui_tab","name":"Home","icon":"dashboard","disabled":false,"hidden":false}]
EDIT, removed the "id" property of led elements. Not needed for now and probably will make confusion if you try to multiply the rows
Also the input is not string anymore
Thank you it works OK and I am very grateful, it will take me a while to understand what is going on and how it works.
Many thanks again for your expertise.
As you can see - the CSS is pulled out and applies to every ui_template you will create if you use same classes for elements. So the "red led" is drawn always same. And of course you will need to define all needed colors in CSS.. You probably need to fine-tune the look of them, what I did is very robust.
Also I left inline css for static elements. (bar and title) That can be easily also moved to the CSS cos if multiple of such used, they most probably will share same style.
Side note - names of the classes written like it is now .red { ...}
is actually bad idea. Much better will be to use some kind of indicator as part of name. Like .led-red {...}
or something like this.
Hi @hotNipi, Thank you so much for the example, I have detected body bg colour and changed suffix accordingly and it works quite well. Now that I can see it working it appears like the background-color and box-shadow colours also meed adjusting in line with the theme in use.
I appreciate the problem of css class collisions thank you, and '.led-red' etc is the way to go. My original problem did not use named colours but instead the #hhhhhh format. With named colour classes the range of usable colours is fixed to the css.
Is it possible to just style the background-color and box-shadow colours according to the dark/light theme in operation and allow the full colour range to be displayed using this html ?
<div style="width: 98.5%; flex: 1; overflow: hidden; position: absolute; top: 3px; left: 6px; padding: 0px;">{{msg.title1}}
<div style="min-width: 0; position: relative; float:right; padding-right: 7px;">
<span ng-repeat="led in msg.bank1 track by $index" style="position: relative; float: right;">
<span class="led-squarex" style="background-color: {{msg.bank1[$index]}}; box-shadow: black 0 -1px 1px 0px, inset black 0 -1px 4px, {{msg.bank1[$index]}} 0 3px 3px;"></span>
</span>
</div>
</div>
<div style="width: 98.5%; flex: 1; overflow: hidden; position: absolute; top: 27px; left: 6px; padding: 0px;">{{msg.title2}}
<div style="min-width: 0; position: relative; float:right; padding-right: 7px;">
<span ng-repeat="led in msg.bank2 track by $index" style="position: relative; float: right;">
<span class="led-squarex" style="background-color: {{msg.bank2[$index]}}; box-shadow: black 0 -1px 1px 0px, inset black 0 -1px 4px, {{msg.bank2[$index]}} 0 3px 3px;"></span>
</span>
</div>
</div>
Thank you again for your help on this.
I suppose I could have #00000 as unused and change it to #ffffff for light theme then all I need is a box-shadow for dark and box-shadow for light.
By having created rules for all colors of led's you'll be using you have done probably huge amount of work and for result you have fine-defined look for them.
Yeah, it is a a lot of playing with shadow colors and positions and stuff.
And yes, you can create all colors for light and dark themes.
.led-red-light {... }
.led-red-dark (...)
For sure it can be done much more simple way - the shadows defined in the way that they do not need coloring so you can use whatever color for led background.
This is question about art and user needs. I can't say if there is way you'll accept it. May be.
Also there is CSS technique to define shades of color variables in HSL format and then you can do pretty neat calculations to have darker or lighter colors of some base color. Pretty complicated stuff but worth of learning ...
Also - the shadows are not only thing to make a led pixel to look realistic.
To create it by using pseudo elements (:before and :after) you can probably again use base color (as CSS variable) to colorize the decorative part.
And most probably there is many more ways....
I really don't have time to create universal color-independent solution. It is hard work. Does not come within minutes.
I understand. Thank you for the detailed insight. At least now I have some more options. Thank you very much for your help I will try and figure it out.
Best regards oz.
I like Kevin Powell and the way he explains and teach the CSS. There is a lot to watch and learn. I really suggest.
For glowing effect he has pretty neat solution for buttons from where I think I'd steal some ideas for nice looking led's. Create a neon button with a reflection using CSS - YouTube
Thank you just had a look. Nice resource thank you for sharing.