Skip to content
This repository has been archived by the owner on Aug 10, 2024. It is now read-only.

Using timers in Js events (store on the $scope)

bartbutenaers edited this page Nov 29, 2021 · 1 revision

This tutorial explains how to use timers in Js event handlers, to execute periodically repetitive tasks on the client side (i.e. inside in the dashboard). And how these timers can be started and stopped by injecting input messages.

A similar effect could be achieved on the server side, by an Inject-node that periodically injects an input message. However this would produce a lot of messages being send from the server to the client, resulting in a waste of bandwidth usage and latency.

  1. Suppose the SVG consists out of a green rectangle with id "my_rectangle":

    rectangle

  2. We want to start a timer when the following input message is injected:

    {
       payload: "start_timer",
       topic:   "custom_msg" 
    }
    

    Note: the topic "custom_msg" is required, when the payload content is a freely choosen. Such messages can be used to control a Js event handler function, which can do stuff based on the data in the message.

  3. And stop that same timer again afterwards, when the following input message is injected:

    {
       payload: "stop_timer",
       topic:   "custom_msg"
    }
    
  4. When these input message arrives, a Js event handler should be executed:

    Js events

  5. In the corresponding Javascript event handler code, a new timer will be started when the payload is "start_timer". And that timer should be stopped, when the input msg payload is "stop_timer":

    Code

    Some remarks regarding this code snippet:

    • Line 3: only create a new timer, when NO previous timer is already running. To avoid multiple timers running in parallel.
    • Line 4: create a new timer, and store a reference to it in a property "myTimer" of the $scope object. That is an AngularJs object where you can store data, and use it again when the next message arrives.
    • Line 6: inside the callback function, apply the random color as "fill" color of the rectangle. You can use both plain Javascript syntax or JQuery syntax. This callback function will be called every time the timer is executed.
    • Line 7: besides the callback function, the timer requires an interval (in milliseconds). The timer will call the callback function at those regular time intervals.
    • Line 11: only stop the timer, only when that timer has already been created.
    • Line 12: stop the timer.
    • Line 13: remove the reference to the timer from the $scope object.

The following demo shows that the color of the rectangle will get a new color every second, as long as the timer is active:

demo_js_timer

The following example flow contains all the coding of this tutorial:

flow

[{"id":"62d3e34714881022","type":"ui_svg_graphics","z":"dd961d75822d1f62","group":"c20e25fb6de0c5b9","order":0,"width":0,"height":0,"svgString":"<svg x=\"0\" y=\"0\" height=\"100\" viewBox=\"0 0 100 100\" width=\"100\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:svg=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n <g id=\"test\" >\n <rect id= \"my_rectangle\" x=\"0\" y=\"0\" width=\"45\" height=\"45\" fill=\"green\" />\n</g>\n</svg>","clickableShapes":[],"javascriptHandlers":[{"selector":"","action":"msg","sourceCode":"switch(msg.payload) {\n    case \"start_timer\":\n        if(!$scope.myTimer) {\n            $scope.myTimer = setInterval(function() {\n                var randomColor = \"#\" + Math.random().toString(16).slice(2, 8).toUpperCase();\n                $(\"#my_rectangle\").css(\"fill\", randomColor);\n            }, 1000);\n        }\n        break;\n    case \"stop_timer\":\n        if($scope.myTimer) {\n            clearInterval($scope.myTimer);\n            $scope.myTimer = null;\n        }\n        break;\n}\n\n\n\n\n\n\n"}],"smilAnimations":[],"bindings":[],"showCoordinates":false,"autoFormatAfterEdit":false,"showBrowserErrors":true,"showBrowserEvents":false,"enableJsDebugging":false,"sendMsgWhenLoaded":false,"noClickWhenDblClick":false,"outputField":"payload","editorUrl":"//drawsvg.org/drawsvg.html","directory":"","panning":"disabled","zooming":"disabled","panOnlyWhenZoomed":false,"doubleClickZoomEnabled":false,"mouseWheelZoomEnabled":false,"dblClickZoomPercentage":150,"cssString":"div.ui-svg svg{\n    color: var(--nr-dashboard-widgetColor);\n    fill: currentColor !important;\n}\ndiv.ui-svg path {\n    fill: inherit !important;\n}","name":"","x":460,"y":1440,"wires":[[]]},{"id":"a14058eed534879a","type":"inject","z":"dd961d75822d1f62","name":"Start timer","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"custom_msg","payload":"start_timer","payloadType":"str","x":280,"y":1420,"wires":[["62d3e34714881022"]]},{"id":"905f048865b2a319","type":"inject","z":"dd961d75822d1f62","name":"Stop timer","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"custom_msg","payload":"stop_timer","payloadType":"str","x":280,"y":1460,"wires":[["62d3e34714881022"]]},{"id":"c20e25fb6de0c5b9","type":"ui_group","name":"JS timer demo","tab":"a28ff08f.3a822","order":1,"disp":true,"width":"30","collapse":false,"className":""},{"id":"a28ff08f.3a822","type":"ui_tab","name":"SVG","icon":"dashboard","order":38,"disabled":false,"hidden":false}]