🍣 FlexDash: some like it raw!

While working with Bart porting node-red-ui-svg to FlexDash (see also [ANNOUNCE] node-red-contrib-svg-edit: beta 1.0.0 some interesting ideas came up in order to support SVGs in FlexDash. What started as an SVG widget turned into a far more general HTML widget:

  • Inject raw HTML into a FlexDash widget and thereby display anything HTML allows
  • Send the widget messages to modify what is being displayed using JQuery-like commands
  • Since SVG behaves like HTML in this context you can use the HTML node to display and manipulate SVG

Here's what the HTML node+widget supports:

  • send it a payload with HTML/SVG and that replaces the content of the widget
  • send it messages with JQuery-like commands to edit the HTML/SVG

Demo

Here's a little video showing this in action. What you're seeing is an initial SVG showing a floorplan injected as payload. Then a little flow animates a red and a green circle through the floorplan. The animation is performed by sending JQuery-like commands to the HTML node.

flexdash-svg1

The commands look something like this:

commands: [
    {
        selector: "#green-dot",
        command: "attr",
        args: [ "cx", path[ix].x ],
    }, {
        selector: ".",
        command: "attr",
        args: ["cy", path[ix].y],
    }
]

This is basically the equivalent of

$('#green-dot')
  .attr('cx', path[ix].x)
  .attr('cy', path[ix].y)

The selector is a JQuery selector and currently supports tag, #id, .class, [attr=value] selectors as well as nesting with a space (#red-circle circle). The . selector says to reuse the same selector result as for the previous command.
The command is a JQuery function, here the attr() function to set the 'cx' and 'cy' attributes of the green circle.
The args are the JQuery arguments, here the attribute name and the value.

The above can be reproduced by installing @tve/node-red-fd-html and running the flow fetched from https://tve.s3.amazonaws.com/public/fd-svg-demo.json (it's too big to post here due to the SVG).

Implementation

Most likely you imagine that the HTML node works by packaging the incoming messages, sending them to FlexDash, and having FlexDash call JQuery to inject the HTML or perform the commands. That's not at all how it works! It's actually much more sophisticated.

The reason is that the HTML widget follows one of the basic principles of FlexDash which says that all browsers see the same view, even if some arrived late. So what's happening under the hood is that the HTML is built on the server side (i.e. in Node-RED) and is then "reflected" to the browsers. Thus the server always has the current state of the HTML contents and can initialize any browser that connects with the current state. Once initialized, browsers can receive incremental updates.

So the JQuery-like HTML editing messages are processed in Node-RED, not in the browser. Right now the incremental update stuff is not really implemented and I'm shipping the full HTML at every update. Hooking incremental updates into the code is trivial but I'm debating about two different ways to do it and want to experiment more with the two options before deciding. In either case, it's "just a performance optimization" and changes neither the behavior nor the API.

I should add that the node-red-fd-html node is still pretty basic and experimental. The editing UI in the flow editor has a preview of the widget content. It looks something like this:

I put that in on a whim, but I'm not sure how useful it is in the end. I have some ideas, but they may not pan out and I'll remove that again. Suggestions welcome...

:rocket:

7 Likes

I see that this is installed like a traditional node-RED contrib node, is this a change in direction for the future installation of flexdash nodes/widgets?

1 Like

There is no direction other than :rocket: :laughing:

Seriously, the node-red-fd-testnodes are also installed the same way. The core widgets are different because they're built into FlexDash and the node is auto-generated.

I expect I will build the HTML node into node-red-flexdash or something like that, but right now it's written in typescript and there are a bunch of helper files and tests so I didn't want to throw the whole shebang into node-red-flexdash.

To build custom stuff for FlexDash I recommend using the Custom Widget to get started, but depending on the functionality at some point it becomes best/necessary to write a contrib node the old fashioned way. It's not fully documented but the docs do have most of the info and there's node-red-fd-testnodes and now node-red-fd-html as samples. If anyone needs help or a little "getting started" repo LMK!

Whoops, I think I didn't fully build node-red-fd-html, so I think it'll only work while the FlexDash dev server is enabled. Ugh, I'll fix that is a little bit (have to run some errands now).

1 Like

Fixed. Published as v0.1.12. It's also in the flow library now and can be installed via the palette manager. Aaand, the floorplan example I pasted above is in the flow library as well, so you can pull-up the example from the install menu.

Please refresh any FlexDash browser after installing node-red-fd-html so the new widget gets loaded.

(I you are installing node-red-fd-html using the palette manager without having node-red-flexdash already installed you will have to restart node-red before FlexDash works properly.)

2 Likes

Ready for the next level???

aarree yyoouuuuu rreeaaddyyyyyy? :joy:

This is the next level:
flexdash-svg2

Yup, you are seeing that right, that's a standard FlexDash SparkLine widget embedded right in the middle of the SVG! It's not overlaid at the HTML level (which is possible too), it's a "foreign object" inside the SVG and gets scaled with the SVG. And yup, in the Node-RED flow there's the corresponding SparkLine node which receives the waveform data just as you would expect:

My demo here is a bit of a hack, I need to get some stuff in order before I can release this but that's the roadmap ahead: full design flexibility in FlexDash, display anything you want anyway you want and embed widgets (or panels) right into it!
:firecracker:

5 Likes

It took me way too long to get that I'm not watching at a board with a microchip but at the floor plan with a table. That "Core2" matched my expectations :wink:

2 Likes

Nice !

If someone wants to skip coding and do it in 98% in inkscape. In my project I have not only possibility to embed graphs but many others.

Look for oiyshTerminal or otdm-yss

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