# Build automatic hyperlink in html table

**URL:** <https://discourse.nodered.org/t/build-automatic-hyperlink-in-html-table/36832>\
**Category:** General\
**Created:** [1 December 2020 20:49 UTC](https://discourse.nodered.org/t/build-automatic-hyperlink-in-html-table/36832 "2020-12-01T20:49:41Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Vonksmurf](https://avatars.discourse-cdn.com/v4/letter/v/5daacb/32.png) [@Vonksmurf](https://discourse.nodered.org/u/Vonksmurf)\
**Post date:** [1 December 2020 20:49 UTC](https://discourse.nodered.org/t/build-automatic-hyperlink-in-html-table/36832/1 "2020-12-01T20:49:41Z")

</div>

hi all  
i used the topic below to make a csv feed ping table.  
everything is working fine, but it would be nice if the ip adres in the table were a hyperlink and when clicked opens in a new browser page  
can anyone help me where to add that in the code to make it work

> [@Monitoring IoT by Ping](https://discourse.nodered.org/t/monitoring-iot-by-ping/23718):
>
> Hello I monitor some IoT by ping. These are then displayed in green or red on the dashboard if they are alive or not. The more there are the more work and maintenance there is. Is there a way where I read a comma or semicolon separated IP list and query them one by one so that all IPs are shown in the dashboard? Today: Ping Node manual IP Adress enteed\> Function msg.payload = msg.payload !== false ? "true": "false"; switch (msg.payload) { case "false" : msg.color = "red"; brea…

thanks in advance

Mark

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [1 December 2020 20:53 UTC](https://discourse.nodered.org/t/build-automatic-hyperlink-in-html-table/36832/2 "2020-12-01T20:53:25Z")

</div>

It would probably help if you posted a bit more about where you've got to. Are you struggling with getting an IP address that is already in a msg into an output string for example or struggling to extract the IP address out of a longer string?

---

<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:** [1 December 2020 22:52 UTC](https://discourse.nodered.org/t/build-automatic-hyperlink-in-html-table/36832/3 "2020-12-01T22:52:57Z")

</div>

You mean like this?  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/4/c/4c58ce4111c0a08c379550f9dd2c4d2bac32dae2.png)

```auto
[{"id":"6a22dd6e.c56fc4","type":"inject","z":"b83d9b41.9c80c8","name":" ***Setup devices to ping here***","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"20","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[{\"name\":\"router\",\"host\":\"192.168.1.1\",\"link\":\"http://192.168.1.1/router.html\"},{\"name\":\"tv\",\"host\":\"192.168.1.46\",\"link\":\"http://192.168.1.46/channels.html\"},{\"name\":\"smart speaker\",\"host\":\"192.168.1.23\"},{\"name\":\"bad device\",\"host\":\"192.168.2.99\"}]","payloadType":"json","x":380,"y":180,"wires":[["4a46702f.96858"]]},{"id":"3539c581.74c1aa","type":"template","z":"b83d9b41.9c80c8","name":"build html table","field":"html","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"\n<table width=\"100%\">\n <tr>\n <th>Name</th>\n <th>Host</th> \n <th>Status</th> \n </tr>\n {{#tableData}}\n <tr class='{{rowclass}}'>\n <td>{{{name}}}</td>\n {{#link}}\n <td><a href=\"{{link}}\" target=\"_blank\">{{host}}</a> </td>\n {{/link}}\n {{^link}}\n <td>{{host}}</td>\n {{/link}} \n <td>{{{stateInfo}}}</i></td> \n </tr>\n {{/tableData}}\n</table>","x":720,"y":240,"wires":[["db2a0a6.457cef8","83b23a6b.400778"]]},{"id":"db2a0a6.457cef8","type":"debug","z":"b83d9b41.9c80c8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":890,"y":280,"wires":[]},{"id":"df081fcf.27c53","type":"inject","z":"b83d9b41.9c80c8","name":"","repeat":"30","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[{\"name\":\"router\",\"ip\":\"192.168.0.1\"},{\"name\":\"tv\",\"ip\":\"192.168.0.51\"},{\"name\":\"smart speaker\",\"ip\":\"192.168.0.52\"},{\"name\":\"bad device\",\"ip\":\"192.168.1.99\"}]","payloadType":"json","x":290,"y":240,"wires":[["823e24a1.87a718"]]},{"id":"823e24a1.87a718","type":"function","z":"b83d9b41.9c80c8","name":"convert pingResults to array","func":"let pingResults = flow.get(\"pingResults\") || {}\nlet now = new Date();\n\nlet tableData = [];\nfor (let k in pingResults) {\n let r = pingResults[k];\n r.age = now - r.timestamp\n if(r.age > 18000){\n r.state = \"old\"\n }\n if(r.state == \"ok\"){\n r.rowclass = \"good\";\n r.stateInfo = '<i class=\"fa fa-thumbs-up\" aria-hidden=\"true\"></i> OK'\n } else if(r.state == \"ng\") {\n r.rowclass = \"bad\";\n r.stateInfo = '<i class=\"fa fa-thumbs-down\" aria-hidden=\"true\"></i> NG'\n } else {\n r.rowclass = \"unknown\";\n r.stateInfo = '<i class=\"fa question\" aria-hidden=\"true\"></i> ' + r.state\n }\n tableData.push(r);\n}\n\nmsg.tableData = tableData\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":500,"y":240,"wires":[["3539c581.74c1aa","793afa09.1583c4"]]},{"id":"4a46702f.96858","type":"ping","z":"b83d9b41.9c80c8","mode":"triggered","name":"","host":"","timer":"20","inputs":1,"x":590,"y":180,"wires":[["fecfa19a.356ee"]]},{"id":"1b75c1a7.006c3e","type":"debug","z":"b83d9b41.9c80c8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":890,"y":180,"wires":[]},{"id":"fecfa19a.356ee","type":"function","z":"b83d9b41.9c80c8","name":"Store Results","func":"let pingResults = flow.get(\"pingResults\") || {}\nlet thisPing = pingResults[msg.topic] || {};\nlet success = msg.payload !== false && msg.payload >= 0;\n\nthisPing.name = msg.ping.name;\nthisPing.host = msg.ping.host;\nthisPing.link = msg.ping.link;\nthisPing.timestamp = new Date();\nthisPing.responseTime = success ? msg.payload : null;\nthisPing.state = success ? \"ok\" : \"ng\" ;\n\npingResults[msg.topic] = thisPing;//store ping obj in pingResults\nflow.set(\"pingResults\",pingResults);//save pingResults in flow context\n\nmsg.payload = thisPing;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":740,"y":180,"wires":[["1b75c1a7.006c3e"]]},{"id":"83b23a6b.400778","type":"ui_template","z":"b83d9b41.9c80c8","group":"9f4f9ffc.07f2a","name":"","order":3,"width":"6","height":"5","format":"<style>\ntable {\n color: #333;\n font-family: Helvetica, Arial, sans-serif;\n width: 100%;\n border-collapse: collapse;\n border-spacing: 0;\n}\ntd, th {\n border: 1px solid transparent;\n /* No more visible border */\n height: 30px;\n transition: all 0.3s;\n /* Simple transition for hover effect */\n}\nth {\n background: #DFDFDF;\n /* Darken header a bit */\n font-weight: bold;\n}\ntd {\n background: #FAFAFA;\n text-align: center;\n}\n\n/* Cells in even rows (2,4,6...) are one color */\n\ntr:nth-child(even) td {\n background: #F1F1F1;\n}\n\n/* Cells in odd rows (1,3,5...) are another (excludes header cells) */\n\ntr:nth-child(odd) td {\n background: #FEFEFE;\n}\ntr td:hover {\n background: #666;\n color: #FFF;\n}\n\n/* Hover cell effect! */ \n\ntr.good {\n color: green;\n}\n\ntr.bad {\n color: red;\n}\n\ntr.unknown {\n color: orange;\n}\n\n \n</style>\n<div ng-bind-html=\"msg.html\"></div>\n","storeOutMessages":true,"fwdInMessages":true,"templateScope":"local","x":900,"y":240,"wires":[[]]},{"id":"793afa09.1583c4","type":"debug","z":"b83d9b41.9c80c8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":650,"y":320,"wires":[]},{"id":"9f4f9ffc.07f2a","type":"ui_group","name":"Default","tab":"5132060d.4cde48","order":1,"disp":true,"width":"6","collapse":false},{"id":"5132060d.4cde48","type":"ui_tab","name":"Home","icon":"dashboard","disabled":false,"hidden":false}]

```

---

<div class="post-metadata">

**Author:** ![Vonksmurf](https://avatars.discourse-cdn.com/v4/letter/v/5daacb/32.png) [@Vonksmurf](https://discourse.nodered.org/u/Vonksmurf)\
**Post date:** [2 December 2020 10:30 UTC](https://discourse.nodered.org/t/build-automatic-hyperlink-in-html-table/36832/4 "2020-12-02T10:30:47Z")

</div>

Thanks Steve,  
This is what i was looking for.  
thank you very much for thinking along

regards mark

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [2 December 2020 20:06 UTC](https://discourse.nodered.org/t/build-automatic-hyperlink-in-html-table/36832/5 "2020-12-02T20:06:18Z")

</div>

OK, you should note that I've taken a slightly different route for my own home dashboard. I run an nmap scan on my system using a shell script fired regularly by CRON (so runs in the OS with sudo rights). The output of the nmap is an XML file and the last step of the script is to use curl to touch an http endpoint in Node-RED. That fires the flow you can see that grabs the XML, translates it to JSON and puts it through a function node to update a retained Node-RED variable along with outputs to MQTT.

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/9/1/9165ebba87494cb6f8654a3463d0465ad29f7a4a.png)

```bash
#! /usr/bin/env bash
# Fast scan the local network for live devices and record
# to /tmp/nmap.xml which can be used in Node-RED
#
# To run manually:
# sudo /home/home/nrmain/system/nmap_scan.sh
#
# To run via cron:
# sudo crontab -e
# 01,16,31,46 * * * * /home/home/nrmain/system/nmap_scan.sh

# Run the scan
nmap -sn --oX /tmp/nmap.xml --privileged -R --system-dns --webxml 192.168.1.0/24
# Make sure ownership & ACLs on the output are secure
chown root:home /tmp/nmap.xml
chmod --silent 640 /tmp/nmap.xml
# Trigger the Node-RED update
curl --insecure -I 'https://localhost:1880/localnetscan'

```

Here is an example of the resulting devices table. Note that there are some fields I can edit as well.

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/6/e/6ea317274852bcaaeecd1b7a076cdafe64af6038.png)

---

<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:** [16 December 2020 20:06 UTC](https://discourse.nodered.org/t/build-automatic-hyperlink-in-html-table/36832/6 "2020-12-16T20:06:19Z")

</div>

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