Mechanical counter display

Just for fun.

image

[{"id":"656888cd7308428e","type":"inject","z":"bf0d83d32eec75c2","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"1","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":230,"y":860,"wires":[["b7f0df3f43a8dc6e"]]},{"id":"b7f0df3f43a8dc6e","type":"function","z":"bf0d83d32eec75c2","name":"random data","func":"let current = context.get('current') || 1\n\ncurrent += Math.floor(Math.random()*2);\nif(current > 999999){\n    current = 1\n}\n\ncontext.set('current',current)\nmsg.payload = current \nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":390,"y":860,"wires":[["aac264ba0df29e45"]]},{"id":"bf8580a24000c55c","type":"ui_template","z":"bf0d83d32eec75c2","group":"55888982bdd0637f","name":"display","order":5,"width":0,"height":0,"format":"<div id=\"{{'slot_'+$id+'_0'}}\" class=\"slot\" ng-init=\"init()\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_1'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_2'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_3'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_4'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_5'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div class=\"gap\"></div>\n<div id=\"{{'slot_'+$id+'_6'}}\" class=\"slot last\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_7'}}\" class=\"slot last\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div class=\"unit\">kWh</div>\n\n<script>\n    (function(scope) {\n        let lock = 0\n        const count = 8\n        scope.previous = Array(count).fill(-1);\n        scope.drawlist = Array(count).fill(true);\n        scope.inited = false\n        scope.waitingData = null       \n        scope.init = function(){\n            if($(\"#slot_\"+scope.$id+\"_0\".length)){\n                actuallyInit()\n            }\n            else{\n                setTimeout(function(){\n                    actuallyInit()\n                },40)\n            }\n        }\n        function actuallyInit(){            \n            lock = 0\n            if(scope.waitingData){                \n                setTimeout(function(){\n                    callDraw()\n                },40)\n            }\n            scope.inited = true\n        }\n\n        scope.$watch('msg', function(msg) {\n            if (msg) { \n                let data = msg.payload.toString().split('')\n                if(!scope.inited){\n                    scope.waitingData = data\n                    return\n                }\n                if(checkCollapsed()){\n                    scope.waitingData = data\n                    return\n                }\n                if(locked()){\n                    scope.waitingData = data\n                    validateLocks()\n                }\n                else{\n                    if(!draw(data)){\n                        scope.waitingData = data\n                        setTimeout(function(){\n                            validateLocks()\n                        },40)\n                    }\n                    \n                }\n            }\n        });\n\n        function checkCollapsed(){\n           let d =  $(\"#slot_\"+scope.$id+\"_0\").closest('.nr-dashboard-cardcontainer').css('display')\n           if(d == 'none'){\n              lock = 0\n              return true\n           }\n           return false\n        }\n\n        function locked(){\n            return lock > 0 \n        }\n\n        function pickLock(){\n            if(locked()){\n                lock --;\n            }\n            if(lock < 0){\n                lock = 0;\n                return\n            }\n            if(!locked()){\n                if(scope.waitingData){\n                    setTimeout(function(){\n                        callDraw()\n                    },10)                    \n                }\n            }\n        }\n\n        function validateLocks(){\n            let e = 0\n            for(let i = 0;i<count;++i){\n                e += $(\"#slot_\"+scope.$id+\"_\"+i).find(\".current\").text().length\n            }          \n            if(e == 0){                \n                lock = 0\n                callDraw()\n            }\n        }\n\n        function callDraw(){           \n            if(!scope.waitingData){\n                return\n            }\n            draw(Array.from(scope.waitingData))            \n            scope.waitingData = null;\n        }\n\n        function draw(data){\n            if(locked()){                \n                return\n            }\n            let failures = 0            \n            while(data.length < count){\n                data.unshift(\"0\")\n            }\n            data.forEach((d,i)=>{\n                //d = parseInt(d)\n                if(scope.previous[i] == d && $(\"#slot_\"+scope.$id+\"_\"+i).find(\".current\").text().length > 0){\n                    scope.drawlist[i] = false\n                }\n                else{\n                    scope.previous[i] = d\n                    scope.drawlist[i] = true\n                    lock ++;\n                }            \n            })\n            data.forEach((d,i) => {\n                if(scope.drawlist[i] == false){\n                    return\n                }\n                let current = $(\"#slot_\"+scope.$id+\"_\"+i).find(\".current\")\n                let next = $(\"#slot_\"+scope.$id+\"_\"+i).find(\".next\")\n                let old = $(\"#slot_\"+scope.$id+\"_\"+i).find(\".old\")            \n           \n                if(next.length == 0 && old.length > 0){\n                    old.removeClass(\"old\").addClass(\"next\")\n                    next = $(\"#slot_\"+scope.$id+\"_\"+i).find(\".next\")\n                }\n                \n                next.text(data[i])\n                if(next.length == 0){                   \n                    failures ++\n                }               \n                current.removeClass(\"current\").addClass(\"old\").on('transitionend webkitTransitionEnd oTransitionEnd', function () {\n                    old = $(\"#slot_\"+scope.$id+\"_\"+i).find(\".old\")\n                    old.off('transitionend webkitTransitionEnd oTransitionEnd')\n                    old.removeClass(\"old\").addClass(\"next\")\n                    pickLock()\n                });\n                next.removeClass(\"next\").addClass(\"current\")\n               \n            })\n            return failures == 0\n        }\n})(scope);\n</script>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":true,"templateScope":"local","className":"roll-display","x":560,"y":900,"wires":[[]]},{"id":"f94b5cb02555e740","type":"ui_template","z":"bf0d83d32eec75c2","group":"674712f8d915bcc0","name":"display css","order":8,"width":0,"height":0,"format":"<style id='roll-display-styles'>\n    .roll-display {\n        --size: 2;\n        --speed: .95;\n        display: flex;\n        align-content: center;\n        justify-content: center;\n        align-items: center;\n        flex-direction: row;\n        overflow: hidden;\n    }\n\n    .roll-display .slot {\n        height: calc(var(--size) * 1em);\n        width: calc(var(--size) * .8em);\n        text-align: center;\n        line-height: calc(var(--size) * 1em);\n        outline: 1px solid #4d4d4d;\n        outline-offset: -3px;\n        border: 3px solid #000000a3;\n        border-radius: 6px;\n        position: relative;\n        overflow: hidden;\n        background: linear-gradient(0deg, #161616, #7e7e7e, #161616);\n    }\n\n    .roll-display .last {\n        background: linear-gradient(0deg, #5a5a5a, #e5e5e5, #5d5d5d);\n    }\n\n    .roll-display .num {\n        position: absolute;\n        left: 0;\n        right: 0;\n        user-select: none;\n        font-size: calc(var(--size) *.7em);\n    }\n\n    .roll-display .last>.num {\n        color: #2f2f2f;\n    }\n\n    .roll-display .num:after {\n        content: \"\";\n        position: absolute;\n        left: -2%;\n        width: 20%;\n        top: 0;\n        height: 100%;\n        background: linear-gradient(to bottom,\n                #00000050,\n                #00000050 50%,\n                transparent 50%,\n                transparent);\n        background-size: 100% 7%;\n    }\n    \n    .roll-display .num:before {\n        content: \"\";\n        position: absolute;\n        right: -2%;\n        width: 20%;\n        top: 0;\n        height: 100%;\n        background: linear-gradient(to bottom,\n                #00000050,\n                #00000050 50%,\n                transparent 50%,\n                transparent);\n        background-size: 100% 7%;\n    }\n\n    .roll-display .last>.num:before{\n        background: linear-gradient(to bottom,\n        #00000030,\n        #00000030 50%,\n        transparent 50%,\n        transparent);\n        background-size: 100% 7%;\n    }\n    \n    .roll-display .last>.num:after{\n        background: linear-gradient(to bottom,\n        #00000030,\n        #00000030 50%,\n        transparent 50%,\n        transparent);\n        background-size: 100% 7%;\n    }\n\n    .roll-display .current {\n        top: 0%;\n        transition: top calc(var(--speed) *1s) ease-in;\n    }\n\n    .roll-display .old {\n        top: 100%;\n        transition: top calc(var(--speed) *1s) ease-in;\n    }\n\n    .roll-display .next {\n        top: -100%;\n        transition: none;\n    }\n\n    .roll-display .gap {\n        position: relative;\n        width: 8px;\n    }\n\n    .roll-display .gap:after {\n        content: '•';\n        position: absolute;\n        text-align: center;\n        inset: 0;\n        color: #b9b9b9;\n    }\n\n    .roll-display .label {\n        display: flex;\n        flex-direction: column;\n        justify-content: center;\n        padding-right: 1em;\n    }\n\n    .roll-display .unit {\n        display: flex;\n        flex-direction: column;\n        justify-content: center;\n        padding-left: 0.5em;\n    }\n</style>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":true,"templateScope":"global","className":"","x":570,"y":820,"wires":[[]]},{"id":"aac264ba0df29e45","type":"ui_template","z":"bf0d83d32eec75c2","group":"55888982bdd0637f","name":"display last 2 red","order":5,"width":0,"height":0,"format":"<style>\n    .roll-display.red .last>.num {\n        color: #bd1818;\n       /* text-shadow: 0px 0px 1px black;*/\n    }\n</style>\n\n<div id=\"{{'slot_'+$id+'_0'}}\" class=\"slot\" ng-init=\"init()\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_1'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_2'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_3'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_4'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_5'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div class=\"gap\"></div>\n<div id=\"{{'slot_'+$id+'_6'}}\" class=\"slot last\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_7'}}\" class=\"slot last\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div class=\"unit\">MWh</div>\n\n<script>\n    (function(scope) {\n        let lock = 0\n        const count = 8\n        scope.previous = Array(count).fill(-1);\n        scope.drawlist = Array(count).fill(true);\n        scope.inited = false\n        scope.waitingData = null       \n        scope.init = function(){\n            if($(\"#slot_\"+scope.$id+\"_0\".length)){\n                actuallyInit()\n            }\n            else{\n                setTimeout(function(){\n                    actuallyInit()\n                },40)\n            }\n        }\n        function actuallyInit(){            \n            lock = 0\n            if(scope.waitingData){                \n                setTimeout(function(){\n                    callDraw()\n                },40)\n            }\n            scope.inited = true\n        }\n\n        scope.$watch('msg', function(msg) {\n            if (msg) { \n                let data = msg.payload.toString().split('')\n                if(!scope.inited){\n                    scope.waitingData = data\n                    return\n                }\n                if(checkCollapsed()){\n                    scope.waitingData = data\n                    return\n                }\n                if(locked()){\n                    scope.waitingData = data\n                    validateLocks()\n                }\n                else{\n                    if(!draw(data)){\n                        scope.waitingData = data\n                        setTimeout(function(){\n                            validateLocks()\n                        },40)\n                    }\n                    \n                }\n            }\n        });\n\n        function checkCollapsed(){\n           let d =  $(\"#slot_\"+scope.$id+\"_0\").closest('.nr-dashboard-cardcontainer').css('display')\n           if(d == 'none'){\n              lock = 0\n              return true\n           }\n           return false\n        }\n\n        function locked(){\n            return lock > 0 \n        }\n\n        function pickLock(){\n            if(locked()){\n                lock --;\n            }\n            if(lock < 0){\n                lock = 0;\n                return\n            }\n            if(!locked()){\n                if(scope.waitingData){\n                    setTimeout(function(){\n                        callDraw()\n                    },10)                    \n                }\n            }\n        }\n\n        function validateLocks(){\n            let e = 0\n            for(let i = 0;i<count;++i){\n                e += $(\"#slot_\"+scope.$id+\"_\"+i).find(\".current\").text().length\n            }          \n            if(e == 0){                \n                lock = 0\n                callDraw()\n            }\n        }\n\n        function callDraw(){           \n            if(!scope.waitingData){\n                return\n            }\n            draw(Array.from(scope.waitingData))            \n            scope.waitingData = null;\n        }\n\n        function draw(data){\n            if(locked()){                \n                return\n            }\n            let failures = 0            \n            while(data.length < count){\n                data.unshift(\"0\")\n            }\n            data.forEach((d,i)=>{\n                //d = parseInt(d)\n                if(scope.previous[i] == d && $(\"#slot_\"+scope.$id+\"_\"+i).find(\".current\").text().length > 0){\n                    scope.drawlist[i] = false\n                }\n                else{\n                    scope.previous[i] = d\n                    scope.drawlist[i] = true\n                    lock ++;\n                }            \n            })\n            data.forEach((d,i) => {\n                if(scope.drawlist[i] == false){\n                    return\n                }\n                let current = $(\"#slot_\"+scope.$id+\"_\"+i).find(\".current\")\n                let next = $(\"#slot_\"+scope.$id+\"_\"+i).find(\".next\")\n                let old = $(\"#slot_\"+scope.$id+\"_\"+i).find(\".old\")            \n           \n                if(next.length == 0 && old.length > 0){\n                    old.removeClass(\"old\").addClass(\"next\")\n                    next = $(\"#slot_\"+scope.$id+\"_\"+i).find(\".next\")\n                }\n                \n                next.text(data[i])\n                if(next.length == 0){                   \n                    failures ++\n                }               \n                current.removeClass(\"current\").addClass(\"old\").on('transitionend webkitTransitionEnd oTransitionEnd', function () {\n                    old = $(\"#slot_\"+scope.$id+\"_\"+i).find(\".old\")\n                    old.off('transitionend webkitTransitionEnd oTransitionEnd')\n                    old.removeClass(\"old\").addClass(\"next\")\n                    pickLock()\n                });\n                next.removeClass(\"next\").addClass(\"current\")\n               \n            })\n            return failures == 0\n        }\n})(scope);\n</script>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":true,"templateScope":"local","className":"roll-display red","x":590,"y":860,"wires":[[]]},{"id":"608b4f75f0cdc9b1","type":"function","z":"bf0d83d32eec75c2","name":"random data","func":"let current = context.get('current') || 1\n\ncurrent += Math.floor(Math.random()*100);\nif(current > 999999){\n    current = 1\n}\n\ncontext.set('current',current)\nmsg.payload = current \nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":390,"y":900,"wires":[["bf8580a24000c55c"]]},{"id":"93a93c8c71124851","type":"inject","z":"bf0d83d32eec75c2","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"2","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":230,"y":900,"wires":[["608b4f75f0cdc9b1"]]},{"id":"55888982bdd0637f","type":"ui_group","name":"1. group","tab":"62083694d0eab7ca","order":1,"disp":true,"width":"6","collapse":false,"className":""},{"id":"674712f8d915bcc0","type":"ui_group","name":"1. group","tab":"8482b305c416b850","order":1,"disp":true,"width":"6","collapse":true,"className":"ordered-1"},{"id":"62083694d0eab7ca","type":"ui_tab","name":"Home","icon":"dashboard","order":1,"disabled":false,"hidden":false},{"id":"8482b305c416b850","type":"ui_tab","name":"Away","icon":"dashboard","disabled":false,"hidden":false}]
13 Likes

Now I will have to find a way to use this in my dashboard :wink:

Speaking of which I'm already trying to modify this https://discourse.nodered.org/t/dashboard-tips-let-the-ui-text-act-as-level-gauge-diy-gauge-examples/40878

My curtains have 2 motors which are separate so it needs to accept 2 values 1 for left and 1 for right.

Any tips :thinking:

PS you should post these in the flows section !!

It really is a widget for the node-red dashboard only and there isn't much a flow shared.

For curtains:
$("#level_"+scope.$id).find(".levelbody.side") selects left and right
$("#level_"+scope.$id).find(".levelbody.side.left") selects left only
$("#level_"+scope.$id).find(".levelbody.side.right") selects right only

Please make this to display current time. This is excellent

I tried modifying your code, but this is not looking elegant, how do i control the spaces to get a compact clock ?

image

[{"id":"656888cd7308428e","type":"inject","z":"d12f70e7abaacb43","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"1","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":350,"y":2340,"wires":[["b7f0df3f43a8dc6e","7298fbb97901e0de"]]},{"id":"7298fbb97901e0de","type":"simpletime","z":"d12f70e7abaacb43","name":"","mydate":true,"myymd":true,"myyear":true,"mymonth":true,"mymonthn":true,"mydom":true,"mydoy":true,"myday":true,"myhourpm":true,"myhour":true,"mytime":true,"mytimes":true,"myminute":true,"myminutes":true,"mysecond":true,"mymillis":true,"myepoch":true,"myrawdate":true,"mypm":true,"x":520,"y":2340,"wires":[["ba666f4f58d33ae3"]]},{"id":"ba666f4f58d33ae3","type":"change","z":"d12f70e7abaacb43","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"mytimes","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":700,"y":2340,"wires":[["a664b3b1662e2510"]]},{"id":"a664b3b1662e2510","type":"ui_template","z":"d12f70e7abaacb43","group":"513419908d693a02","name":"display","order":5,"width":0,"height":0,"format":"<style>\n    .roll-display {\n        display: flex;\n        align-content: center;\n        justify-content: flex-start;\n        flex-direction: row;\n    }\n    .slot {\n        height: 1.6em;\n        width: 1.2em;\n        text-align: center;\n        line-height: 1.6em;\n        border: 4px solid #000000a3;\n        border-radius: 6px;\n        border-top-width: 8px;\n        border-bottom-width: 8px;\n        position: relative;\n        overflow: hidden;\n        background: linear-gradient(0deg, #5a5a5a, #b7b7b7,#5d5d5d);\n    }\n    .num{\n        position:absolute;\n        left: 0;\n        right: 0;\n        user-select:none;\n        background: linear-gradient(0deg, #0000005e, #4c4c4c42, #0000005e);\n    } \n    .current{       \n        top:0em;\n        transition: top 0.25s;\n    }\n    .old{\n        top:1.6em;\n        transition: top 0.25s;\n    }\n    .next{\n        top:-1.6em;\n        transition: none;\n    }\n    .last > .num{\n       \n        background: linear-gradient(0deg, #53535300, #d5d5d52e, #53535300);\n        color: #464646;\n        font-weight: 700;\n        \n    }\n    .gap {\n        position:relative;\n        width: 8px;\n    }\n    .gap:after {\n        content:'•';\n        position:absolute;\n        bottom:0;\n        color:#a4a4a4;\n    }\n    .label{\n        display: flex;\n        flex-direction: column;\n        justify-content: center;\n        padding-right:1em;\n    }\n</style>\n\n<div class=\"label\">COUNTER</div>\n\n<div id=\"{{'slot_'+$id+'_0'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n\n<div id=\"{{'slot_'+$id+'_1'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n\n<div id=\"{{'slot_'+$id+'_2'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n\n<div class=\"gap\"></div>\n\n<div id=\"{{'slot_'+$id+'_3'}}\" class=\"slot last\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n\n<div class=\"gap\"></div>\n\n<div id=\"{{'slot_'+$id+'_4'}}\" class=\"slot last\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n\n<div id=\"{{'slot_'+$id+'_5'}}\" class=\"slot last\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n\n<div class=\"gap\"></div>\n\n<div id=\"{{'slot_'+$id+'_6'}}\" class=\"slot last\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n\n<div id=\"{{'slot_'+$id+'_7'}}\" class=\"slot last\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n\n<script>\n    (function(scope) {\n        let lock = false\n        scope.previous = [-1,-1,-1,-1,-1,-1,-1,-1]\n        scope.drawlist = [true,true,true,true,true,true,true,true]\n        scope.$watch('msg', function(msg) {\n            if (msg) { \n                if(lock){\n                   // console.log(\"locked\")\n                    lock = false\n                    return\n                }  \n               // console.log(msg.payload)\n                lock = true \n\n                let data = msg.payload.toString().split('')\n                while(data.length < 8){\n                    data.unshift(0)\n                }\n\n                data.forEach((d,i) => \n                {\n                    d = parseInt(d)\n                    if(scope.previous[i] == d){\n                        scope.drawlist[i] = false\n                    }\n                    else{\n                        scope.previous[i] = d\n                        scope.drawlist[i] = true\n                    }\n\n                })\n                \n                data.forEach((d,i) => {\n                    if(scope.drawlist[i] == false){\n                        return\n                    }\n                    let current = $(\"#slot_\"+scope.$id+\"_\"+i).find(\".current\")\n                    let next = $(\"#slot_\"+scope.$id+\"_\"+i).find(\".next\")\n                    let old = $(\"#slot_\"+scope.$id+\"_\"+i).find(\".old\")\n\n                    if(next.length == 0 && old.length > 0){\n                        next = old\n                        next.removeClass(\"old\").addClass(\"next\")\n                    }                    \n\n                    next.text(data[i])\n                    current.removeClass(\"current\").addClass(\"old\").on('transitionend webkitTransitionEnd oTransitionEnd', function () {\n                        old = $(\"#slot_\"+scope.$id+\"_\"+i).find(\".old\")\n                        old.removeClass(\"old\").addClass(\"next\")\n                        lock = false\n                    });\n                    next.removeClass(\"next\").addClass(\"current\")\n                })\n            }\n    });\n})(scope);\n</script>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":true,"templateScope":"local","className":"roll-display","x":860,"y":2340,"wires":[[]]},{"id":"513419908d693a02","type":"ui_group","name":"HEADER","tab":"d90e028674af84a9","order":1,"disp":false,"width":"42","collapse":false,"className":""},{"id":"d90e028674af84a9","type":"ui_tab","name":"LIVE","icon":"dashboard","order":1,"disabled":false,"hidden":false}]

Modified to display time.
image

There is too many time formats so I give up immediately to provide any smart solution ...

[{"id":"534bdb8d43678c2a","type":"ui_template","z":"bf0d83d32eec75c2","group":"674712f8d915bcc0","name":"display","order":5,"width":0,"height":0,"format":"<style>\n    .roll-display {\n        display: flex;\n        align-content: center;\n        justify-content: flex-start;\n        flex-direction: row;\n    }\n    .slot {\n        height: 1.6em;\n        width: 1.2em;\n        text-align: center;\n        line-height: 1.6em;\n        border: 4px solid #000000a3;\n        border-radius: 6px;\n        border-top-width: 8px;\n        border-bottom-width: 8px;\n        position: relative;\n        overflow: hidden;\n        background: linear-gradient(0deg, #5a5a5a, #b7b7b7,#5d5d5d);\n    }\n    .num{\n        position:absolute;\n        left: 0;\n        right: 0;\n        user-select:none;\n        background: linear-gradient(0deg, #0000005e, #4c4c4c42, #0000005e);\n    } \n    .current{       \n        top:0em;\n        transition: top 0.25s;\n    }\n    .old{\n        top:1.6em;\n        transition: top 0.25s;\n    }\n    .next{\n        top:-1.6em;\n        transition: none;\n    }\n    .last > .num{\n       \n        background: linear-gradient(0deg, #53535300, #d5d5d52e, #53535300);\n        color: #464646;\n        font-weight: 700;\n        \n    }\n    .gap {\n        position:relative;\n        width: 8px;\n    }\n    .gap:after {\n        content:'•';\n        position:absolute;\n        bottom:0;\n        color:#a4a4a4;\n    }\n    .label{\n        display: flex;\n        flex-direction: column;\n        justify-content: center;\n        padding-right:1em;\n    }\n</style>\n\n\n<div id=\"{{'slot_'+$id+'_0'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_1'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_2'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_3'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_4'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_5'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n\n<div id=\"{{'slot_'+$id+'_6'}}\" class=\"slot last\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_7'}}\" class=\"slot last\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n\n<script>\n    (function(scope) {\n        let lock = false\n        scope.previous = [-1,-1,-1,-1,-1,-1,-1,-1]\n        scope.drawlist = [true,true,true,true,true,true,true,true]\n        scope.$watch('msg', function(msg) {\n            if (msg) { \n\n                let time = new Date(msg.payload).toTimeString().split(\" \")[0]\n                console.log(time)\n\n                if(lock){\n                   // console.log(\"locked\")\n                    lock = false\n                    return\n                }  \n               // console.log(msg.payload)\n                lock = true \n\n                let data = time.split('')\n                while(data.length < 8){\n                    data.unshift(0)\n                }\n\n                data.forEach((d,i) => \n                {\n                    //d = parseInt(d)\n                    if(scope.previous[i] == d){\n                        scope.drawlist[i] = false\n                    }\n                    else{\n                        scope.previous[i] = d\n                        scope.drawlist[i] = true\n                    }\n\n                })\n                \n                data.forEach((d,i) => {\n                    if(scope.drawlist[i] == false){\n                        return\n                    }\n                    let current = $(\"#slot_\"+scope.$id+\"_\"+i).find(\".current\")\n                    let next = $(\"#slot_\"+scope.$id+\"_\"+i).find(\".next\")\n                    let old = $(\"#slot_\"+scope.$id+\"_\"+i).find(\".old\")\n\n                    if(next.length == 0 && old.length > 0){\n                        next = old\n                        next.removeClass(\"old\").addClass(\"next\")\n                    }                    \n\n                    next.text(data[i])\n                    current.removeClass(\"current\").addClass(\"old\").on('transitionend webkitTransitionEnd oTransitionEnd', function () {\n                        old = $(\"#slot_\"+scope.$id+\"_\"+i).find(\".old\")\n                        old.removeClass(\"old\").addClass(\"next\")\n                        lock = false\n                    });\n                    next.removeClass(\"next\").addClass(\"current\")\n                })\n            }\n    });\n})(scope);\n</script>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":true,"templateScope":"local","className":"roll-display","x":580,"y":740,"wires":[[]]},{"id":"f2fbe600d2ab5417","type":"inject","z":"bf0d83d32eec75c2","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"1","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":430,"y":740,"wires":[["534bdb8d43678c2a"]]},{"id":"674712f8d915bcc0","type":"ui_group","name":"1. group","tab":"62083694d0eab7ca","order":1,"disp":true,"width":"6","collapse":true,"className":"ordered-1"},{"id":"62083694d0eab7ca","type":"ui_tab","name":"Home","icon":"dashboard","order":1,"disabled":false,"hidden":false}]
2 Likes

Hi,
I enlarged the slot but I can't enlarge the font ...
Can you help me?

0003

I would like to create this ... approximately .....

Modified the time version to have size a bit dynamically changeable

image

[{"id":"bf8580a24000c55c","type":"ui_template","z":"bf0d83d32eec75c2","group":"674712f8d915bcc0","name":"display","order":5,"width":0,"height":0,"format":"<style>\n    .roll-display {\n        --size:4;\n        display: flex;\n        align-content: center;\n        justify-content: flex-start;\n        flex-direction: row;\n    }\n    .slot {\n        height: calc(var(--size) * 1em);\n        width: calc(var(--size) * .8em);\n        text-align: center;\n        line-height: calc(var(--size) * 1em);\n        border: 4px solid #000000a3;\n        border-radius: 6px;\n        border-top-width: 8px;\n        border-bottom-width: 8px;\n        position: relative;\n        overflow: hidden;\n        background: linear-gradient(0deg, #5a5a5a, #b7b7b7,#5d5d5d);\n    }\n    .num{\n        position:absolute;\n        left: 0;\n        right: 0;\n        user-select:none;\n        font-size:calc(var(--size) *.7em);\n        background: linear-gradient(0deg, #0000005e, #4c4c4c42, #0000005e);\n    } \n    .current{       \n        top:0em;\n        transition: top 0.25s;\n    }\n    .old{\n        top:calc(var(--size) * 1em);\n        transition: top 0.25s;\n    }\n    .next{\n        top:calc(var(--size) * -1em);\n        transition: none;\n    }\n    .last > .num{\n       \n        background: linear-gradient(0deg, #53535300, #d5d5d52e, #53535300);\n        color: #464646;\n        font-weight: 700;\n        \n    }\n    .gap {\n        position:relative;\n        width: 8px;\n    }\n    .gap:after {\n        content:'•';\n        position:absolute;\n        bottom:0;\n        color:#a4a4a4;\n    }\n    .label{\n        display: flex;\n        flex-direction: column;\n        justify-content: center;\n        padding-right:1em;\n    }\n</style>\n\n\n<div id=\"{{'slot_'+$id+'_0'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_1'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_2'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_3'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_4'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_5'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n\n<div id=\"{{'slot_'+$id+'_6'}}\" class=\"slot last\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_7'}}\" class=\"slot last\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n\n<script>\n    (function(scope) {\n        let lock = false\n        scope.previous = [-1,-1,-1,-1,-1,-1,-1,-1]\n        scope.drawlist = [true,true,true,true,true,true,true,true]\n        scope.$watch('msg', function(msg) {\n            if (msg) { \n\n                let time = new Date(msg.payload).toTimeString().split(\" \")[0]\n                console.log(time)\n\n                if(lock){\n                   // console.log(\"locked\")\n                    lock = false\n                    return\n                }  \n               // console.log(msg.payload)\n                lock = true \n\n                let data = time.split('')\n                while(data.length < 8){\n                    data.unshift(0)\n                }\n\n                data.forEach((d,i) => \n                {\n                    //d = parseInt(d)\n                    if(scope.previous[i] == d){\n                        scope.drawlist[i] = false\n                    }\n                    else{\n                        scope.previous[i] = d\n                        scope.drawlist[i] = true\n                    }\n\n                })\n                \n                data.forEach((d,i) => {\n                    if(scope.drawlist[i] == false){\n                        return\n                    }\n                    let current = $(\"#slot_\"+scope.$id+\"_\"+i).find(\".current\")\n                    let next = $(\"#slot_\"+scope.$id+\"_\"+i).find(\".next\")\n                    let old = $(\"#slot_\"+scope.$id+\"_\"+i).find(\".old\")\n\n                    if(next.length == 0 && old.length > 0){\n                        next = old\n                        next.removeClass(\"old\").addClass(\"next\")\n                    }                    \n\n                    next.text(data[i])\n                    current.removeClass(\"current\").addClass(\"old\").on('transitionend webkitTransitionEnd oTransitionEnd', function () {\n                        old = $(\"#slot_\"+scope.$id+\"_\"+i).find(\".old\")\n                        old.removeClass(\"old\").addClass(\"next\")\n                        lock = false\n                    });\n                    next.removeClass(\"next\").addClass(\"current\")\n                })\n            }\n    });\n})(scope);\n</script>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":true,"templateScope":"local","className":"roll-display","x":580,"y":780,"wires":[[]]},{"id":"ee10705e762837ef","type":"inject","z":"bf0d83d32eec75c2","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"1","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":430,"y":780,"wires":[["bf8580a24000c55c"]]},{"id":"674712f8d915bcc0","type":"ui_group","name":"1. group","tab":"62083694d0eab7ca","order":1,"disp":true,"width":"6","collapse":true,"className":"ordered-1"},{"id":"62083694d0eab7ca","type":"ui_tab","name":"Home","icon":"dashboard","order":1,"disabled":false,"hidden":false}]
3 Likes

Thank you ....

Found a use for it :wink:

image

Thanks !!

5 Likes

Oh no - I now find myself watching the numbers going up in a pretty but worryingly fast rate :rofl:

8 Likes

Did a bit cleanup in overall look and in the code to improve readability in both areas.

image

[{"id":"656888cd7308428e","type":"inject","z":"bf0d83d32eec75c2","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"1","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":210,"y":820,"wires":[["b7f0df3f43a8dc6e"]]},{"id":"b7f0df3f43a8dc6e","type":"function","z":"bf0d83d32eec75c2","name":"random data","func":"let current = context.get('current') || 1\n\ncurrent += Math.floor(Math.random()*100);\nif(current > 999999){\n    current = 1\n}\n\ncontext.set('current',current)\nmsg.payload = current \nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":370,"y":820,"wires":[["aac264ba0df29e45"]]},{"id":"bf8580a24000c55c","type":"ui_template","z":"bf0d83d32eec75c2","group":"674712f8d915bcc0","name":"display","order":5,"width":0,"height":0,"format":"<div id=\"{{'slot_'+$id+'_0'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_1'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_2'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_3'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_4'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_5'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div class=\"gap\"></div>\n<div id=\"{{'slot_'+$id+'_6'}}\" class=\"slot last\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_7'}}\" class=\"slot last\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div class=\"unit\">kWh</div>\n\n<script>\n    (function(scope) {\n        let lock = false\n        let count = 8\n        scope.previous = Array(count).fill(-1);\n        scope.drawlist = Array(count).fill(true);       \n        scope.$watch('msg', function(msg) {\n            if (msg) { \n                if(lock){\n                    lock = false\n                    return\n                }\n                lock = true \n                let data = msg.payload.toString().split('')\n               \n                while(data.length < count){\n                    data.unshift(\"0\")\n                }\n\n                data.forEach((d,i) => \n                {\n                    //d = parseInt(d)\n                    if(scope.previous[i] == d && $(\"#slot_\"+scope.$id+\"_\"+i).find(\".current\").text().length > 0){\n                        scope.drawlist[i] = false\n                    }\n                    else{\n                        scope.previous[i] = d\n                        scope.drawlist[i] = true\n                    }\n\n                })\n                \n                data.forEach((d,i) => {\n                    if(scope.drawlist[i] == false){\n                        return\n                    }\n                    let current = $(\"#slot_\"+scope.$id+\"_\"+i).find(\".current\")\n                    let next = $(\"#slot_\"+scope.$id+\"_\"+i).find(\".next\")\n                    let old = $(\"#slot_\"+scope.$id+\"_\"+i).find(\".old\")\n\n                    if(next.length == 0 && old.length > 0){\n                        next = old\n                        next.removeClass(\"old\").addClass(\"next\")\n                    }                    \n\n                    next.text(data[i])\n                    current.removeClass(\"current\").addClass(\"old\").on('transitionend webkitTransitionEnd oTransitionEnd', function () {\n                        old = $(\"#slot_\"+scope.$id+\"_\"+i).find(\".old\")\n                        old.removeClass(\"old\").addClass(\"next\")\n                        lock = false\n                    });\n                    next.removeClass(\"next\").addClass(\"current\")\n                })\n            }\n    });\n})(scope);\n</script>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":true,"templateScope":"local","className":"roll-display","x":560,"y":840,"wires":[[]]},{"id":"f94b5cb02555e740","type":"ui_template","z":"bf0d83d32eec75c2","group":"674712f8d915bcc0","name":"dixplay css","order":8,"width":0,"height":0,"format":"<style id='roll-display-styles'>\n    .roll-display {\n        --size: 2;\n        --speed: .95;\n        display: flex;\n        align-content: center;\n        justify-content: center;\n        align-items: center;\n        flex-direction: row;\n        overflow: hidden;\n    }\n\n    .roll-display .slot {\n        height: calc(var(--size) * 1em);\n        width: calc(var(--size) * .8em);\n        text-align: center;\n        line-height: calc(var(--size) * 1em);\n        outline: 1px solid #4d4d4d;\n        outline-offset: -3px;\n        border: 3px solid #000000a3;\n        border-radius: 6px;\n        position: relative;\n        overflow: hidden;\n        background: linear-gradient(0deg, #161616, #7e7e7e, #161616);\n    }\n\n    .roll-display .last {\n        background: linear-gradient(0deg, #5a5a5a, #e5e5e5, #5d5d5d);\n    }\n\n    .roll-display .num {\n        position: absolute;\n        left: 0;\n        right: 0;\n        user-select: none;\n        font-size: calc(var(--size) *.7em);\n    }\n\n    .roll-display .last>.num {\n        color: #2f2f2f;\n    }\n\n    .roll-display .num:after {\n        content: \"\";\n        position: absolute;\n        left: -2%;\n        width: 20%;\n        top: 0;\n        height: 100%;\n        background: linear-gradient(to bottom,\n                #00000050,\n                #00000050 50%,\n                transparent 50%,\n                transparent);\n        background-size: 100% 7%;\n    }\n    \n    .roll-display .num:before {\n        content: \"\";\n        position: absolute;\n        right: -2%;\n        width: 20%;\n        top: 0;\n        height: 100%;\n        background: linear-gradient(to bottom,\n                #00000050,\n                #00000050 50%,\n                transparent 50%,\n                transparent);\n        background-size: 100% 7%;\n    }\n\n    .roll-display .last>.num:before{\n        background: linear-gradient(to bottom,\n        #00000030,\n        #00000030 50%,\n        transparent 50%,\n        transparent);\n        background-size: 100% 7%;\n    }\n    \n    .roll-display .last>.num:after{\n        background: linear-gradient(to bottom,\n        #00000030,\n        #00000030 50%,\n        transparent 50%,\n        transparent);\n        background-size: 100% 7%;\n    }\n\n    .roll-display .current {\n        top: 0%;\n        transition: top calc(var(--speed) *1s) ease-in;\n    }\n\n    .roll-display .old {\n        top: 100%;\n        transition: top calc(var(--speed) *1s) ease-in;\n    }\n\n    .roll-display .next {\n        top: -100%;\n        transition: none;\n    }\n\n    .roll-display .gap {\n        position: relative;\n        width: 8px;\n    }\n\n    .roll-display .gap:after {\n        content: '•';\n        position: absolute;\n        text-align: center;\n        inset: 0;\n        color: #b9b9b9;\n    }\n\n    .roll-display .label {\n        display: flex;\n        flex-direction: column;\n        justify-content: center;\n        padding-right: 1em;\n    }\n\n    .roll-display .unit {\n        display: flex;\n        flex-direction: column;\n        justify-content: center;\n        padding-left: 0.5em;\n    }\n</style>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":true,"templateScope":"local","className":"","x":570,"y":880,"wires":[[]]},{"id":"aac264ba0df29e45","type":"ui_template","z":"bf0d83d32eec75c2","group":"674712f8d915bcc0","name":"display last 2 red","order":5,"width":0,"height":0,"format":"<style>\n    .roll-display.red .last>.num {\n        color: #bd1818;\n       /* text-shadow: 0px 0px 1px black;*/\n    }\n</style>\n\n<div id=\"{{'slot_'+$id+'_0'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_1'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_2'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_3'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_4'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_5'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div class=\"gap\"></div>\n<div id=\"{{'slot_'+$id+'_6'}}\" class=\"slot last\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_7'}}\" class=\"slot last\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div class=\"unit\">MWh</div>\n\n<script>\n    (function(scope) {\n        let lock = false\n        let count = 8\n        scope.previous = Array(count).fill(-1);\n        scope.drawlist = Array(count).fill(true);       \n        scope.$watch('msg', function(msg) {\n            if (msg) { \n                if(lock){\n                    lock = false\n                    return\n                }\n                lock = true \n                let data = msg.payload.toString().split('')\n               \n                while(data.length < count){\n                    data.unshift(\"0\")\n                }\n\n                data.forEach((d,i) => \n                {                    \n                    if(scope.previous[i] == d && $(\"#slot_\"+scope.$id+\"_\"+i).find(\".current\").text().length > 0){\n                        scope.drawlist[i] = false\n                    }\n                    else{\n                        scope.previous[i] = d\n                        scope.drawlist[i] = true\n                    }\n\n                })\n                \n                data.forEach((d,i) => {\n                    if(scope.drawlist[i] == false){\n                        return\n                    }\n                    let current = $(\"#slot_\"+scope.$id+\"_\"+i).find(\".current\")\n                    let next = $(\"#slot_\"+scope.$id+\"_\"+i).find(\".next\")\n                    let old = $(\"#slot_\"+scope.$id+\"_\"+i).find(\".old\")\n\n                    if(next.length == 0 && old.length > 0){\n                        next = old\n                        next.removeClass(\"old\").addClass(\"next\")\n                    }                    \n\n                    next.text(data[i])\n                    current.removeClass(\"current\").addClass(\"old\").on('transitionend webkitTransitionEnd oTransitionEnd', function () {\n                        old = $(\"#slot_\"+scope.$id+\"_\"+i).find(\".old\")\n                        old.removeClass(\"old\").addClass(\"next\")\n                        lock = false\n                    });\n                    next.removeClass(\"next\").addClass(\"current\")\n                })\n            }\n    });\n})(scope);\n</script>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":true,"templateScope":"local","className":"roll-display red","x":590,"y":800,"wires":[[]]},{"id":"608b4f75f0cdc9b1","type":"function","z":"bf0d83d32eec75c2","name":"random data","func":"let current = context.get('current') || 1\n\ncurrent += Math.floor(Math.random()*50);\nif(current > 999999){\n    current = 1\n}\n\ncontext.set('current',current)\nmsg.payload = current \nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":370,"y":860,"wires":[["bf8580a24000c55c"]]},{"id":"93a93c8c71124851","type":"inject","z":"bf0d83d32eec75c2","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"1.1","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":210,"y":860,"wires":[["608b4f75f0cdc9b1"]]},{"id":"674712f8d915bcc0","type":"ui_group","name":"1. group","tab":"62083694d0eab7ca","order":1,"disp":true,"width":"6","collapse":true,"className":"ordered-1"},{"id":"62083694d0eab7ca","type":"ui_tab","name":"Home","icon":"dashboard","order":1,"disabled":false,"hidden":false}]
5 Likes

You really should put these in the flows section - they are a great resource.

Easier to find there than searching through old posts.

1 Like

Is there an easy way to get it to refresh all digits when changing tabs, (without having to refresh the whole page) ?

I am loving it !

How can i make the Unit Display (°C) slightly larger to match the display font ?

time_temp

1 Like

Not easy but it's done now.

[{"id":"bf8580a24000c55c","type":"ui_template","z":"bf0d83d32eec75c2","group":"674712f8d915bcc0","name":"display","order":5,"width":0,"height":0,"format":"<div id=\"{{'slot_'+$id+'_0'}}\" class=\"slot\" ng-init=\"init()\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_1'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_2'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_3'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_4'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_5'}}\" class=\"slot\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div class=\"gap\"></div>\n<div id=\"{{'slot_'+$id+'_6'}}\" class=\"slot last\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div id=\"{{'slot_'+$id+'_7'}}\" class=\"slot last\">\n    <div class=\"num current\"></div>\n    <div class=\"num next\"></div>\n</div>\n<div class=\"unit\">kWh</div>\n\n<script>\n    (function(scope) {\n        let lock = 0\n        const count = 8\n        scope.previous = Array(count).fill(-1);\n        scope.drawlist = Array(count).fill(true);\n        scope.inited = false\n        scope.waitingData = null       \n        scope.init = function(){\n            if($(\"#slot_\"+scope.$id+\"_0\".length)){\n                actuallyInit()\n            }\n            else{\n                setTimeout(function(){\n                    actuallyInit()\n                },40)\n            }\n        }\n        function actuallyInit(){\n            console.log('actuallyInit')  \n            lock = 0\n            if(scope.waitingData){\n                console.log('draw from waitingData:',scope.waitingData)\n                setTimeout(function(){\n                    callDraw()\n                },40)\n            }\n            scope.inited = true\n        }\n        scope.$watch('msg', function(msg) {\n            if (msg) { \n                let data = msg.payload.toString().split('')\n                if(!scope.inited){\n                    scope.waitingData = data\n                    return\n                }\n                if(locked()){\n                    scope.waitingData = data\n                    validateLocks()\n                }\n                else{\n                    if(!draw(data)){\n                        scope.waitingData = data\n                        setTimeout(function(){\n                            validateLocks()\n                        },40)\n                    }\n                    \n                }\n            }\n        });\n\n        function locked(){\n            return lock > 0 \n        }\n\n        function pickLock(){\n            if(locked()){\n                lock --;\n            }\n            if(lock < 0){\n                lock = 0;\n                return\n            }\n            if(!locked()){\n                if(scope.waitingData){\n                    setTimeout(function(){\n                        callDraw()\n                    },10)                    \n                }\n            }\n        }\n\n        function validateLocks(){\n            let e = 0\n            for(let i = 0;i<count;++i){\n                e += $(\"#slot_\"+scope.$id+\"_\"+i).find(\".current\").text().length\n            }          \n            if(e == 0){                \n                lock = 0\n                callDraw()\n            }\n        }\n\n        function callDraw(){           \n            if(!scope.waitingData){\n                return\n            }\n            draw(Array.from(scope.waitingData))            \n            scope.waitingData = null;\n        }\n\n        function draw(data){\n            if(locked()){                \n                return\n            }\n            let failures = 0            \n            while(data.length < count){\n                data.unshift(\"0\")\n            }\n            data.forEach((d,i)=>{\n                //d = parseInt(d)\n                if(scope.previous[i] == d && $(\"#slot_\"+scope.$id+\"_\"+i).find(\".current\").text().length > 0){\n                    scope.drawlist[i] = false\n                }\n                else{\n                    scope.previous[i] = d\n                    scope.drawlist[i] = true\n                    lock ++;\n                }            \n            })\n            data.forEach((d,i) => {\n                if(scope.drawlist[i] == false){\n                    return\n                }\n                let current = $(\"#slot_\"+scope.$id+\"_\"+i).find(\".current\")\n                let next = $(\"#slot_\"+scope.$id+\"_\"+i).find(\".next\")\n                let old = $(\"#slot_\"+scope.$id+\"_\"+i).find(\".old\")            \n           \n                if(next.length == 0 && old.length > 0){\n                    old.removeClass(\"old\").addClass(\"next\")\n                    next = $(\"#slot_\"+scope.$id+\"_\"+i).find(\".next\")\n                }\n                \n                next.text(data[i])\n                if(next.length == 0){                   \n                    failures ++\n                }               \n                current.removeClass(\"current\").addClass(\"old\").on('transitionend webkitTransitionEnd oTransitionEnd', function () {\n                    old = $(\"#slot_\"+scope.$id+\"_\"+i).find(\".old\")\n                    old.off('transitionend webkitTransitionEnd oTransitionEnd')\n                    old.removeClass(\"old\").addClass(\"next\")\n                    pickLock()\n                });\n                next.removeClass(\"next\").addClass(\"current\")\n               \n            })\n            return failures == 0\n        }\n})(scope);\n</script>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":true,"templateScope":"local","className":"roll-display","x":540,"y":860,"wires":[[]]},{"id":"f94b5cb02555e740","type":"ui_template","z":"bf0d83d32eec75c2","group":"674712f8d915bcc0","name":"dixplay css","order":8,"width":0,"height":0,"format":"<style id='roll-display-styles'>\n    .roll-display {\n        --size: 2;\n        --speed: .95;\n        display: flex;\n        align-content: center;\n        justify-content: center;\n        align-items: center;\n        flex-direction: row;\n        overflow: hidden;\n    }\n\n    .roll-display .slot {\n        height: calc(var(--size) * 1em);\n        width: calc(var(--size) * .8em);\n        text-align: center;\n        line-height: calc(var(--size) * 1em);\n        outline: 1px solid #4d4d4d;\n        outline-offset: -3px;\n        border: 3px solid #000000a3;\n        border-radius: 6px;\n        position: relative;\n        overflow: hidden;\n        background: linear-gradient(0deg, #161616, #7e7e7e, #161616);\n    }\n\n    .roll-display .last {\n        background: linear-gradient(0deg, #5a5a5a, #e5e5e5, #5d5d5d);\n    }\n\n    .roll-display .num {\n        position: absolute;\n        left: 0;\n        right: 0;\n        user-select: none;\n        font-size: calc(var(--size) *.7em);\n    }\n\n    .roll-display .last>.num {\n        color: #2f2f2f;\n    }\n\n    .roll-display .num:after {\n        content: \"\";\n        position: absolute;\n        left: -2%;\n        width: 20%;\n        top: 0;\n        height: 100%;\n        background: linear-gradient(to bottom,\n                #00000050,\n                #00000050 50%,\n                transparent 50%,\n                transparent);\n        background-size: 100% 7%;\n    }\n    \n    .roll-display .num:before {\n        content: \"\";\n        position: absolute;\n        right: -2%;\n        width: 20%;\n        top: 0;\n        height: 100%;\n        background: linear-gradient(to bottom,\n                #00000050,\n                #00000050 50%,\n                transparent 50%,\n                transparent);\n        background-size: 100% 7%;\n    }\n\n    .roll-display .last>.num:before{\n        background: linear-gradient(to bottom,\n        #00000030,\n        #00000030 50%,\n        transparent 50%,\n        transparent);\n        background-size: 100% 7%;\n    }\n    \n    .roll-display .last>.num:after{\n        background: linear-gradient(to bottom,\n        #00000030,\n        #00000030 50%,\n        transparent 50%,\n        transparent);\n        background-size: 100% 7%;\n    }\n\n    .roll-display .current {\n        top: 0%;\n        transition: top calc(var(--speed) *1s) ease-in;\n    }\n\n    .roll-display .old {\n        top: 100%;\n        transition: top calc(var(--speed) *1s) ease-in;\n    }\n\n    .roll-display .next {\n        top: -100%;\n        transition: none;\n    }\n\n    .roll-display .gap {\n        position: relative;\n        width: 8px;\n    }\n\n    .roll-display .gap:after {\n        content: '•';\n        position: absolute;\n        text-align: center;\n        inset: 0;\n        color: #b9b9b9;\n    }\n\n    .roll-display .label {\n        display: flex;\n        flex-direction: column;\n        justify-content: center;\n        padding-right: 1em;\n    }\n\n    .roll-display .unit {\n        display: flex;\n        flex-direction: column;\n        justify-content: center;\n        padding-left: 0.5em;\n    }\n</style>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":true,"templateScope":"local","className":"","x":550,"y":900,"wires":[[]]},{"id":"608b4f75f0cdc9b1","type":"function","z":"bf0d83d32eec75c2","name":"random data","func":"let current = context.get('current') || 1\n\ncurrent += Math.floor(Math.random()*100);\nif(current > 999999){\n    current = 1\n}\n\ncontext.set('current',current)\nmsg.payload = current \nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":370,"y":860,"wires":[["bf8580a24000c55c"]]},{"id":"93a93c8c71124851","type":"inject","z":"bf0d83d32eec75c2","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"2","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":210,"y":860,"wires":[["608b4f75f0cdc9b1"]]},{"id":"674712f8d915bcc0","type":"ui_group","name":"1. group","tab":"8482b305c416b850","order":1,"disp":true,"width":"6","collapse":true,"className":"ordered-1"},{"id":"8482b305c416b850","type":"ui_tab","name":"Away","icon":"dashboard","disabled":false,"hidden":false}]
1 Like

The unit has class
.roll-display .unit {

Add font-size to it

1 Like

:+1:

image

image

I keep code updated at first post.
Latest fixes also the issue with collapsed group.

You demo works OK, but when I put new version in my flow it only updates once ?

If I leave old and new version then old version still works ( updates all digits after 1st msg)
New one updates with last value sent, but ignores next msgs, unless I switch tabs and go back. But then doesn't update again.
Cannot figure out what the issue is, I just send same msg.payload with a number to both.

Will do some more testing.

Using old and new together has no guarantees what so ever ...