# Node-red-contrib-ui-svg: experimenting with foreign elements

**URL:** <https://discourse.nodered.org/t/node-red-contrib-ui-svg-experimenting-with-foreign-elements/36777>\
**Category:** Share Your Nodes\
**Created:** [30 November 2020 23:40 UTC](https://discourse.nodered.org/t/node-red-contrib-ui-svg-experimenting-with-foreign-elements/36777 "2020-11-30T23:40:19Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![BartButenaers](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bartbutenaers/32/10476_2.png) [@BartButenaers](https://discourse.nodered.org/u/BartButenaers)\
**Post date:** [30 November 2020 23:40 UTC](https://discourse.nodered.org/t/node-red-contrib-ui-svg-experimenting-with-foreign-elements/36777/1 "2020-11-30T23:40:19Z")

</div>

Hi folks,

Got yesterday a [feature request](https://github.com/bartbutenaers/node-red-contrib-ui-svg/issues/79) on Github to support the `change`event in the SVG node.

Currently the SVG node only supports events triggered by the user (e.g. click, touch, keydown, ...), which you can use to trigger actions inside your Node-RED flow. E.g. to turn on lights, and so on ...

However the `change` doesn't really fit 100% in the list of other events, because the `onchange` event will only be triggered _ **indirectly** _ (e.g. when the user clicks a circle-element -\> a JS event handler sets the value of a text-element -\> the onchange event handler of the text-element is triggered). But currently it is **NOT** possible to trigger the `onchange` event _ **directly** _, for the simple reason that there is no input element in SVG where a user can enter text...

However it is possible to add non-SVG (html) elements iinto an SVG drawing as _ **foreign objects** _, which are [supported](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/foreignObject#Browser_compatibility) in the major browsers. For example you can add an html `input`-element into an SVG:

```auto
<svg preserveAspectRatio="none" x="0" y="0" viewBox="0 0 900 710" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <image width="889" height="703" id="background" xlink:href="https://www.roomsketcher.com/wp-content/uploads/2016/10/1-Bedroom-Floor-Plans.jpg" />
  <foreignObject x="470" y="80" width="100" height="50">
    <input type="number" id="temp_living" min="10" max="25" style="height: 25px;">
    <label for="temp_living" id="temp_living_label" style="color: black;font-size: larger;font-weight: bold;vertical-align: middle;"> °C</label>
  </foreignObject>
</svg>

```

I have created a [change\_event](https://github.com/bartbutenaers/node-red-contrib-ui-svg/tree/change_event) branch to the Github repository, which supports `change` events and a _ **update\_value** _ input command (which can be used to set the value of such an input element via an input message). That branch can be installed like this from within your .node-red folder:

```auto
npm install bartbutenaers/node-red-contrib-ui-svg#change_event

```

The demo below shows this functionality:

- An html input element is displayed inside the SVG drawing.

- When you press enter inside the input-element (or when you press the up/down button of the spinner), an output message - containing the new input value - will be send.

- When the input value is changed, a custom JS client side event handler will be called. This handler will e.g. change the color of the input-element's label, depending on the color:

And this is the final result:

![svg_foreign_input](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/8/3/83f79f5c2c9d2aa1b3c983b631335886630772df.gif)

Here is the flow for those who want to experiment with it:

```auto
[{"id":"107fa0c1.cb755f","type":"debug","z":"42b7b639.325dd8","name":"Changed temperature","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":740,"y":660,"wires":[]},{"id":"58329d91.3fc564","type":"ui_svg_graphics","z":"42b7b639.325dd8","group":"f014eb03.a3c618","order":1,"width":"14","height":"10","svgString":"<svg preserveAspectRatio=\"none\" x=\"0\" y=\"0\" viewBox=\"0 0 900 710\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:svg=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n <image width=\"889\" height=\"703\" id=\"background\" xlink:href=\"https://www.roomsketcher.com/wp-content/uploads/2016/10/1-Bedroom-Floor-Plans.jpg\" />\n <foreignObject x=\"470\" y=\"80\" width=\"100\" height=\"50\">\n <input type=\"number\" id=\"temp_living\" min=\"10\" max=\"25\" style=\"height: 25px;\">\n <label for=\"temp_living\" id=\"temp_living_label\" style=\"color: black;font-size: larger;font-weight: bold;vertical-align: middle;\"> °C</label>\n </foreignObject>\n</svg>","clickableShapes":[{"targetId":"#temp_living","action":"change","payload":"temperature_living","payloadType":"str","topic":"temperature_living"}],"javascriptHandlers":[{"selector":"#temp_living","action":"change","sourceCode":"if(evt.target.valueAsNumber < 10) {\n $(\"#temp_living_label\")[0].style.color=\"blue\";\n}\nelse if(evt.target.valueAsNumber > 20) {\n $(\"#temp_living_label\")[0].style.color=\"red\";\n}\nelse {\n $(\"#temp_living_label\")[0].style.color=\"orange\";\n}"}],"smilAnimations":[],"bindings":[],"showCoordinates":false,"autoFormatAfterEdit":false,"showBrowserErrors":false,"showBrowserEvents":false,"enableJsDebugging":true,"sendMsgWhenLoaded":false,"outputField":"","editorUrl":"http://drawsvg.org/drawsvg.html","directory":"","panning":"disabled","zooming":"disabled","panOnlyWhenZoomed":false,"doubleClickZoomEnabled":false,"mouseWheelZoomEnabled":false,"name":"","x":500,"y":660,"wires":[["107fa0c1.cb755f"]]},{"id":"b5bd6668.a54ab8","type":"inject","z":"42b7b639.325dd8","name":"Set default temperature","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"command\":\"update_value\",\"selector\":\"#temp_living\",\"value\":17}","payloadType":"json","x":260,"y":660,"wires":[["58329d91.3fc564"]]},{"id":"f014eb03.a3c618","type":"ui_group","name":"Floorplan test","tab":"80068970.6e2868","order":1,"disp":true,"width":"14","collapse":false},{"id":"80068970.6e2868","type":"ui_tab","name":"SVG","icon":"dashboard","disabled":false,"hidden":false}]

```

The disadvantage is that _ **you need to add the foreign object manually** _ to your SVG. Suppose you have drawn your SVG via a third-party editor (or via the integrated DrawSvg), your foreign objects will be _ **overwritten** _ every time you import an updated drawing from your editor... To solve that, I would have to find a way to specify the foreign objects in the config screen (in a new tabsheet), but no ideas yet how I could achieve this ...

But I believe there will be some interesting IOT use cases for these foreign objects inside an SVG drawing.

As always all 'constructive' feeback is very welcome!!

Have fun with it,  
Bart

---

<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:** [29 January 2021 23:40 UTC](https://discourse.nodered.org/t/node-red-contrib-ui-svg-experimenting-with-foreign-elements/36777/2 "2021-01-29T23:40:21Z")

</div>

This topic was automatically closed after 60 days. New replies are no longer allowed.
