# Dashboard 2 - Rolling Text Display - how to?

**URL:** <https://discourse.nodered.org/t/dashboard-2-rolling-text-display-how-to/90028>\
**Category:** Dashboard\
**Tags:** dashboard-2\
**Created:** [6 August 2024 22:24 UTC](https://discourse.nodered.org/t/dashboard-2-rolling-text-display-how-to/90028 "2024-08-06T22:24:09Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![craigcurtin](https://avatars.discourse-cdn.com/v4/letter/c/94ad74/32.png) [@craigcurtin](https://discourse.nodered.org/u/craigcurtin)\
**Post date:** [6 August 2024 22:24 UTC](https://discourse.nodered.org/t/dashboard-2-rolling-text-display-how-to/90028/1 "2024-08-06T22:24:09Z")

</div>

Hey Guys,

I would like to implement a rolling dashboard display - say 10 lines high - preferably in Dashboard 2

Essentially what i want to do is maintain a queue of messages (probably store in global context) - the display would read from the Queue and would display each message in a 10 line window - say for 10 seconds, then would pop the top one off the screen and move everything up one position and retrieve the next item in the queue and put that at the bottom.

I would use a seperate process to manage the items in the queue - and remove them as required.

The idea is that i could have a schedule of upcoming actions in my home automation system - lets say

6:35 am - Dawn over - external motion sensor off  
6:50 am - Cameras being changed over to daylight mode  
7:00 am - battery system moving from arbitrage to Zero Grid  
7:05 am - Electricity price spike - battery moving back to arbitrage mode

etc etc

Events that were one offs would be deleted out of the queue by a separate process and recurring tasks would be added by their respective process throughout the day - the Global Object would probably be a Javascript array of objects that could be cycled through.

Anyone done something like this or have pointers as to which UI elements could be used ??

Craig

---

<div class="post-metadata">

**Author:** ![craigcurtin](https://avatars.discourse-cdn.com/v4/letter/c/94ad74/32.png) [@craigcurtin](https://discourse.nodered.org/u/craigcurtin)\
**Post date:** [7 August 2024 04:06 UTC](https://discourse.nodered.org/t/dashboard-2-rolling-text-display-how-to/90028/2 "2024-08-07T04:06:08Z")

</div>

Actually a bit more intelligent searching and browsing on the forum led me to a post by @Steve-Mcl which has pretty close to what i want to achieve.

It will be a good start for my first foray into Dashboard 2

Craig

---

<div class="post-metadata">

**Author:** ![dynamicdave](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dynamicdave/32/96_2.png) [@dynamicdave](https://discourse.nodered.org/u/dynamicdave)\
**Post date:** [7 August 2024 05:03 UTC](https://discourse.nodered.org/t/dashboard-2-rolling-text-display-how-to/90028/3 "2024-08-07T05:03:03Z")

</div>

Please note: These suggestions are for Dashboard 1 (will probably need modifying for DB-2).

I made a train arrivals board a few years ago using the 'ring buffer' node.

 ![wed_arrivals_board_A](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/d/9/d9de1dc67813a96b035ec5ae6bd79fe2d959fe50.png)  
Here's part of the NR flow...

```auto
[{"id":"4dc1bb2f.93f96c","type":"group","z":"f233685a.5de4f","name":"","style":{"stroke":"#000000","fill":"#d1d1d1","fill-opacity":"0.51","label":true},"nodes":["f55aa089.ee3a1","10c76796.2a23a8","721e03ac.771e2c","70a4fcad.b5751c","962557b.b9a27a8","e254e87b.dc563","15aba88d.bdb8df","67a87dfc.d11bd4","ea595c5.e38f9a"],"x":1314,"y":779,"w":1032,"h":222},{"id":"f55aa089.ee3a1","type":"ui_template","z":"f233685a.5de4f","g":"4dc1bb2f.93f96c","group":"e6d438e4.34caf8","name":"PR arrivals board","order":1,"width":"8","height":"5","format":"<div ng-bind-html=\"msg.payload\" style=\"overflow:auto\"></div>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":false,"templateScope":"local","className":"","x":2230,"y":960,"wires":[[]]},{"id":"10c76796.2a23a8","type":"function","z":"f233685a.5de4f","g":"4dc1bb2f.93f96c","name":"Move message up the board","func":"let msgArray = msg.payload;\nlet arrLen = msgArray.length;\nlet outLine = \"\";\nfor (let i=0; i < arrLen; i++) {\n outLine = outLine + msgArray[i];\n}\n\nmsg.payload = outLine;\nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1980,"y":960,"wires":[["f55aa089.ee3a1"]]},{"id":"721e03ac.771e2c","type":"ring-buffer","z":"f233685a.5de4f","g":"4dc1bb2f.93f96c","name":"","capacity":"10","order":"old-to-new","sendOnlyIfFull":false,"pushAfterClear":false,"extra":false,"perTopic":false,"x":1750,"y":960,"wires":[["10c76796.2a23a8"]]},{"id":"70a4fcad.b5751c","type":"link in","z":"f233685a.5de4f","g":"4dc1bb2f.93f96c","name":"","links":["f739b4fd.7fc93"],"x":1355,"y":960,"wires":[["e254e87b.dc563"]]},{"id":"962557b.b9a27a8","type":"inject","z":"f233685a.5de4f","g":"4dc1bb2f.93f96c","name":"Clear message board","props":[{"p":"type","v":"clear","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":1460,"y":880,"wires":[["e254e87b.dc563"]]},{"id":"e254e87b.dc563","type":"function","z":"f233685a.5de4f","g":"4dc1bb2f.93f96c","name":"Colour-code stations","func":"if (msg.type == \"clear\") {\n // Clear the ring buffer and pre-load it with newlines <br>\n // This will ensure the user message scrolls from the bottom edge\n \n node.send({'payload.clear':true});\n \n for (let i=0; i<10; i++) {\n node.send ({payload:`${i}<br>`}); \n }\n}\nelse if (msg.station ==\"pr\") {\n var train = msg.train;\n var signal = msg.signal;\n var train_time = msg.train_time;\n var station= msg.station;\n var color = \"green\";\n \n switch (station) {\n\n case \"hw\":\n color = \"#097479\"\n break;\n \n case \"pr\" : \n color = \"#ffdf80\";\n break;\n }\n msg.payload = `<p><font color=\"white\">${train_time} >> </font><font color=${color}>Train-Id: ${train} arrived at Signal-Id: ${signal}</font></p>`;\n return msg;\n}\n\n","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1540,"y":960,"wires":[["721e03ac.771e2c"]]},{"id":"15aba88d.bdb8df","type":"ui_button","z":"f233685a.5de4f","g":"4dc1bb2f.93f96c","name":"","group":"e6d438e4.34caf8","order":2,"width":0,"height":0,"passthru":false,"label":"Click to clear - Arrivals board","tooltip":"","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"","x":1460,"y":820,"wires":[["67a87dfc.d11bd4"]]},{"id":"67a87dfc.d11bd4","type":"change","z":"f233685a.5de4f","g":"4dc1bb2f.93f96c","name":"Clear message board","rules":[{"t":"set","p":"type","pt":"msg","to":"clear","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1720,"y":820,"wires":[["e254e87b.dc563"]]},{"id":"ea595c5.e38f9a","type":"comment","z":"f233685a.5de4f","g":"4dc1bb2f.93f96c","name":"Colour-code the stations on the Arrivals board at PR","info":"","x":2090,"y":820,"wires":[]},{"id":"e6d438e4.34caf8","type":"ui_group","name":"Activity at Princes Risborough","tab":"2333e020.8e09e","order":4,"disp":true,"width":"8","collapse":false},{"id":"2333e020.8e09e","type":"ui_tab","name":"Trainspotting","icon":"dashboard","order":56,"disabled":false,"hidden":false}]

```

Just recently I made a Node Reporting Queue using some JavaScript to create a 'stack manager' where items are pushed onto the bottom of the stack and popped off of the top.

 ![node_reporting_queue_A](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/7/5/75206483a7777bd6db616acf9c55e7ff18c773a0.png)  
 ![node_reporting_queue_B](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/f/8/f8af12725c4f7579206b190cf2784c8fac828f43.png)

Here's part of the NR flow...

```auto
[{"id":"3163af1e1fc49405","type":"function","z":"0f43c63d6bea2b09","name":"Stack manager","func":"let stack = flow.get('stack') || [];\nlet queue_length = flow.get(\"queue_length\") || 0;\n\nif (msg.topic == \"push\") {\n //let stack = flow.get('stack') || [];\n\n let my_node = { \"nodeID\": msg.payload.nodeID, \"location\": msg.payload.location }\n stack.push(my_node);\n flow.set('stack', stack);\n queue_length = queue_length + 1;\n flow.set(\"queue_length\", queue_length);\n return msg;\n}\nelse if (msg.topic == \"pop\") {\n //let stack = flow.get('stack') || [];\n stack.shift();\n // stack.pop();\n flow.set('stack', stack);\n if (queue_length > 0) {\n queue_length = queue_length - 1;\n flow.set(\"queue_length\", queue_length);\n }\n else {\n flow.set(\"queue_length\", 0);\n }\n return msg;\n}\nelse if (msg.topic == \"reset_stack\") {\n flow.set('stack', []);\n queue_length = 0;\n flow.set(\"queue_length\", queue_length);\n //Send payload to clear the UI display\n msg.payload = [];\n return msg;\n}\nelse {\n return null;\n}","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1240,"y":480,"wires":[["c6e3cfdfc9b87adf","30627e1f6e7c8560"]]},{"id":"24ebbf98111b8823","type":"change","z":"0f43c63d6bea2b09","name":"Push node onto stack","rules":[{"t":"set","p":"topic","pt":"msg","to":"push","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1000,"y":480,"wires":[["3163af1e1fc49405"]]},{"id":"adcad4254556d85f","type":"change","z":"0f43c63d6bea2b09","name":"Empty the stack","rules":[{"t":"set","p":"topic","pt":"msg","to":"reset_stack","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":980,"y":520,"wires":[["3163af1e1fc49405"]]},{"id":"61b35001b103e551","type":"change","z":"0f43c63d6bea2b09","name":"Remove node from stack","rules":[{"t":"set","p":"topic","pt":"msg","to":"pop","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1010,"y":440,"wires":[["3163af1e1fc49405"]]},{"id":"9c7a40c5da74e610","type":"ui_table","z":"0f43c63d6bea2b09","group":"b917a40b6565668d","name":"","order":1,"width":6,"height":10,"columns":[{"field":"nodeID","title":"NodeID","width":"30%","align":"left","formatter":"plaintext","formatterParams":{"target":"_blank"}},{"field":"location","title":"Location","width":"70%","align":"left","formatter":"plaintext","formatterParams":{"target":"_blank"}}],"outputs":0,"cts":false,"x":1490,"y":520,"wires":[]},{"id":"9f0d5c43cfe4f9a7","type":"debug","z":"0f43c63d6bea2b09","name":"debug 3450","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1230,"y":560,"wires":[]},{"id":"c6e3cfdfc9b87adf","type":"function","z":"0f43c63d6bea2b09","name":"Clear table then send array","func":"msg.payload = [];\nnode.send(msg);\n\nlet stack = flow.get('stack') || [];\nmsg.payload = stack;\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1280,"y":520,"wires":[["9c7a40c5da74e610","9f0d5c43cfe4f9a7"]]},{"id":"34be0cc278da508e","type":"ui_text","z":"0f43c63d6bea2b09","group":"b917a40b6565668d","order":8,"width":3,"height":1,"name":"Queue length","label":"","format":"Queue length {{msg.payload}}","layout":"row-left","className":"","style":false,"font":"","fontSize":16,"color":"#000000","x":980,"y":640,"wires":[]},{"id":"30627e1f6e7c8560","type":"change","z":"0f43c63d6bea2b09","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"queue_length","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":980,"y":600,"wires":[["34be0cc278da508e"]]},{"id":"b917a40b6565668d","type":"ui_group","name":"Node Reporting Queue","tab":"b73bebe42aae7406","order":2,"disp":true,"width":"6","collapse":false,"className":""},{"id":"b73bebe42aae7406","type":"ui_tab","name":"Global Node Monitor (GNM) v11","icon":"dashboard","order":4,"disabled":false,"hidden":false}]

```

---

<div class="post-metadata">

**Author:** ![craigcurtin](https://avatars.discourse-cdn.com/v4/letter/c/94ad74/32.png) [@craigcurtin](https://discourse.nodered.org/u/craigcurtin)\
**Post date:** [7 August 2024 05:19 UTC](https://discourse.nodered.org/t/dashboard-2-rolling-text-display-how-to/90028/4 "2024-08-07T05:19:03Z")

</div>

Thanks Dave,

Yes i have one from about 5 years ago for Dashboard 1 and it works well - just looking for something for Dashboard 2 - thanks for stepping up - i will have a look at Steves code and see if i can work out what is going on and how it all works

Craig

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [7 August 2024 05:40 UTC](https://discourse.nodered.org/t/dashboard-2-rolling-text-display-how-to/90028/5 "2024-08-07T05:40:41Z")

</div>

Is this the post you were referring to?

> [@A scrolling terminal display in dashboard 2](https://discourse.nodered.org/t/a-scrolling-terminal-display-in-dashboard-2/88423):
>
> Hi all, I did a demo for someone recently and thought I'd share for you all to enjoy (or ignore) I have not made a contrib node out of it, but that would not be too difficult to do. Here is a gif for your viewing pleasure: [chrome\_urnbkVJRsY] [click me for a biglier view](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/4/5/455ac35bbbbe52b1f951827a66d712a9a78a33af.gif) And more importantly, here is the demo flow: [{"id":"575c755afa443ca9","type":"tab","label":"Dashboard terminal","disabled":false,"info":"","env":[]},{"id":"7bab5965093a262f","type":"group","z":"575c755afa443ca9","name":"te…

---

<div class="post-metadata">

**Author:** ![craigcurtin](https://avatars.discourse-cdn.com/v4/letter/c/94ad74/32.png) [@craigcurtin](https://discourse.nodered.org/u/craigcurtin)\
**Post date:** [7 August 2024 07:28 UTC](https://discourse.nodered.org/t/dashboard-2-rolling-text-display-how-to/90028/6 "2024-08-07T07:28:01Z")

</div>

Yes it was - i see i forgot to also put a link to it - DOH !!

Thanks

Craig

---

<div class="post-metadata">

**Author:** ![omrid](https://avatars.discourse-cdn.com/v4/letter/o/77aa72/32.png) [@omrid](https://discourse.nodered.org/u/omrid)\
**Post date:** [7 August 2024 07:57 UTC](https://discourse.nodered.org/t/dashboard-2-rolling-text-display-how-to/90028/7 "2024-08-07T07:57:18Z")

</div>

If you want this on dashboard-2.0 - the equivalent of the `ui-table` node (used above) in dashboard 2.0 is `@omrid01/node-red-dashboard-2-table-tabulator`, which needs to be installed on top of the built-in dashboard 2.0 nodes.

---

<div class="post-metadata">

**Author:** ![craigcurtin](https://avatars.discourse-cdn.com/v4/letter/c/94ad74/32.png) [@craigcurtin](https://discourse.nodered.org/u/craigcurtin)\
**Post date:** [7 August 2024 23:44 UTC](https://discourse.nodered.org/t/dashboard-2-rolling-text-display-how-to/90028/8 "2024-08-07T23:44:26Z")

</div>

Excellent - thanks for the pointer.

I will start with @Steve-Mcl sample stuff first and try to get to grips with all the CSS and HTML (i do networking and security for a living - but am absolute crap at Design, HTML, CSS etc) so it is something new for me.

Once i understand how it all comes together i may challenge myself with your node

regards

Craig

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)\
**Post date:** [21 August 2024 23:44 UTC](https://discourse.nodered.org/t/dashboard-2-rolling-text-display-how-to/90028/9 "2024-08-21T23:44:52Z")

</div>

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.
