CVE-2022-3783 (JavaScript, published 2022-10-31T21:15Z)
Description: value: A vulnerability, which was classified as problematic, has been found in node-red-dashboard. This issue affects some unknown processing of the file components/ui-component/ui-component-ctrl.js of the component ui_text Format Handler. The manipulation leads to cross site scripting. The attack may be initiated remotely. The name of the patch is 9305d1a82f19b235dfad24a7d1dd4ed244db7743. It is recommended to apply a patch to fix this issue. The associated identifier of this vulnerability is VDB-212555.
Severity: nan (CVSS v3 base score: 6.1)
Weakness: CWE-79 \u2014 Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
Repository: https://github.com/node-red/node-red-dashboard
Files changed:
CHANGELOG.md
dist/dashboard.appcache
dist/js/app.min.js
package.json
src/components/ui-component/ui-component-ctrl.js
Commit message: Fix ui_text XSS

to close #772


Vulnerable code:
# Time: Wed May 25 2022 11:23:30 GMT+0100 (British Summer Time)
# hash: 22f744c7102e4eb0375d482c7bd34ac0d407159d34773e84e1f5087d0b6444d3
angular.module("ui").controller("uiComponentController",["$scope","UiEvents","$interpolate","$interval",function(l,u,e,r){this.$onInit=function(){var i,m=this;"string"==typeof m.item.format&&(m.item.getText=e(m.item.format).bind(null,m.item)),"string"==typeof m.item.label&&(m.item.getLabel=e(m.item.label).bind(null,m.item),m.item.safeLabel="nr-dashboard-widget-"+m.item.label.replace(/\W/g,"_")),"string"==typeof m.item.tooltip&&(m.item.getTooltip=e(m.item.tooltip).bind(null,m.item)),"string"==typeof m.item.color&&(m.item.getColor=e(m.item.color).bind(null,m.item)),"string"==typeof m.item.icon&&(m.item.getIcon=e(m.item.icon).bind(null,m.item)),"string"==typeof m.item.units&&(m.item.getUnits=e(m.item.units).bind(null,m.item)),m.init=function(){switch(m.item.type){case"button":m.buttonClick=function(e){n({id:m.item.id,value:m.item.value,event:{clientX:e.originalEvent.clientX,clientY:e.originalEvent.clientY,bbox:[e.originalEvent.clientX-e.originalEvent.layerX,e.originalEvent.clientY-e.originalEvent.layerY+e.currentTarget.clientHeight,e.originalEvent.clientX-e.originalEvent.layerX+e.currentTarget.clientWidth,e.originalEvent.clientY-e.originalEvent.layerY]}},0)};break;case"switch":m.switchClick=function(){n({id:m.item.id,value:!m.item.value},0)};break;case"dropdown":m.searchTerm="",m.selectAll=!1,m.changed=!1,m.itemChanged=function(){m.searchTerm="",m.item.multiple?m.changed=!0:m.valueChanged(0)},m.checkAll=function(){var e=m.item.options.filter(function(e){return e.label.toLowerCase().includes(m.searchTerm.toLowerCase())});m.item.value=m.selectAll?e.map(function(e){return e.value}):[],m.valueChanged(0)},m.closed=function(){m.changed&&(m.changed=!1,m.valueChanged(0))},(m.item.me=m).processInput=function(e){o(e)};break;case"numeric":var i=function(e){m.item.value=parseFloat(m.item.value),isNaN(m.item.value)&&(m.item.value=m.item.min),0<e?(m.item.value==m.item.max&&1==m.item.wrap?m.item.value=m.item.min:m.item.value<m.item.max&&(m.item.value=Math.round(1e4*Math.min(m.item.value+e,m.item.max))/1e4),m.item.value<m.item.min&&(m.item.value=m.item.min)):e<0&&(m.item.value==m.item.min&&1==m.item.wrap?m.item.value=m.item.max:m.item.value>m.item.min&&(m.item.value=Math.round(1e4*Math.max(m.item.value+e,m.item.min))/1e4),m.item.value>m.item.max&&(m.item.value=m.item.max))},e=9.5*(Math.round(1e4*(m.item.min+m.item.step))/1e4).toString().length,t=9.5*(Math.round(1e4*(m.item.max+m.item.step))/1e4).toString().length;m.item.minWidth=t<e?e:t;var a=null;m.newValue=function(){isNaN(parseFloat(m.item.value))||(m.item.value<m.item.min&&(m.item.value=m.item.min),m.item.value>m.item.max&&(m.item.value=m.item.max),u.emit({id:m.item.id,value:m.item.value}))},m.periodicChange=function(e){i(e);var t=0;a=r(function(){75<++t?i(250*e):50<t?i(50*e):35<t?i(10*e):25<t?i(2*e):15<t?i(e):5<t&&t%2&&i(e)},100)},m.stopPeriodic=function(){a&&(r.cancel(a),a=null,m.valueChanged(0))};break;case"chart":m.item.theme=l.main.selectedTab.theme;break;case"colour-picker":(m.item.width<4||!m.item.showValue&&!m.item.showPicker)&&(m.item.showPicker=!1,m.item.showValue=!1,m.item.showSwatch=!0),m.item.showPicker&&m.item.height<4&&(m.item.height=m.item.showSwatch||m.item.showValue?4:3),m.item.options={format:m.item.format,inline:m.item.showPicker,hue:m.item.showHue,alpha:m.item.showAlpha,lightness:m.item.showLightness,swatch:m.item.showSwatch,swatchOnly:m.item.width<2||!m.item.showValue,swatchPos:"right",pos:"bottom right",case:"lower",round:!m.item.square,pickerOnly:m.item.showPicker&&!(m.item.showSwatch||m.item.showValue)},m.item.key=function(e){13!==e.charCode&&13!==e.which&&9!==e.charCode&&9!==e.which||(u.emit({id:m.item.id,value:m.item.value}),m.api&&m.api.close())},m.item.eventapi={onChange:function(e,t,i){void 0!==i&&m.valueChanged(0)},onOpen:function(e,t){m.api=e}},l.$watch("me.item.value",function(){m.item.oldValue||(m.item.oldValue=m.item.value),"true"===m.item.dynOutput&&m.item.value!==m.item.oldValue&&(m.item.oldValue=m.item.value,m.valueChanged(20))});break;case"text-input":case"text-input-CR":-1!=m.item.mode.indexOf("time")&&(m.processInput=function(e){var t=new Date(e.value);if(isNaN(e.value)){var i=e.value.match(/^(\d\d):(\d\d)/);if(null==i){var a=Date.parse(e.value);isNaN(a)&&(a=Date.now()),t=new Date(a)}else t=new Date("1970-01-01 "+i[1]+":"+i[2]+":00Z")}t.setMilliseconds(0),t.setSeconds(0),e.value=t,m.item.value=e.value},m.item.me=m),"week"!==m.item.mode&&"month"!==m.item.mode||(m.processInput=function(e){var t=new Date(e.value);if(isNaN(e.value)){var i=Date.parse(e.value);isNaN(i)&&(i=Date.now()),t=new Date(i)}t.setMilliseconds(0),t.setSeconds(0),e.value=t,m.item.value=e.value},m.item.me=m);break;case"date-picker":void 0!==m.item.ddd&&("number"!=typeof m.item.ddd&&"string"!=typeof m.item.ddd||(m.item.ddd=new Date(m.item.ddd))),m.processInput=function(e){e.value=new Date(e.value),m.item.ddd=e.value},m.setDate=function(){m.item.value=m.item.ddd,m.valueChanged(0)},m.item.me=m;break;case"form":m.processInput=function(e){if("object"==typeof e.value)for(var t in e.value)if(m.item.formValue.hasOwnProperty(t))for(var i in m.item.options)"date"!==m.item.options[i].type&&"time"!==m.item.options[i].type||m.item.options[i].value!==t||(e.value[t]=new Date(e.value[t])),m.item.formValue[t]=e.value[t]},m.item.extraRows=0,m.item.options.map(function(e){"multiline"==e.type&&1<e.rows&&(m.item.extraRows+=e.rows-1)}),m.item.rowCount=1==m.item.splitLayout?Math.ceil(m.item.options.length/2):m.item.options.length,m.item.rowCount+=""==m.item.label?1:2,m.item.rowCount+=m.item.extraRows,m.item.rowHeight=((m.item.rowCount-1)*m.item.sy+(""==m.item.label?.3*m.item.sy:1.2*m.item.sy)+(m.item.rowCount-1)*m.item.cy)/m.item.rowCount,m.stop=function(e){13!==e.charCode&&13!==e.which||(e.preventDefault(),e.stopPropagation())},m.submit=function(){m.item.value=JSON.parse(JSON.stringify(m.item.formValue)),m.valueChanged(0),m.reset()},m.reset=function(){for(var e in m.item.options)"checkbox"===m.item.options[e].type||"switch"===m.item.options[e].type?m.item.formValue[m.item.options[e].value]=!1:m.item.formValue[m.item.options[e].value]="";l.$$childTail.form.$setUntouched(),l.$$childTail.form.$setPristine()},m.item.me=m;break;case"template":m.setFormat=function(e){m.item.format=e},void 0!==m.item.msg&&void 0!==m.item.msg.template&&m.setFormat(m.item.msg.template);break;case"slider":m.wheel=function(e){e.preventDefault(),0<e.originalEvent.deltaY&&(m.item.value+=m.item.step,m.item.value>m.item.max&&(m.item.value=m.item.max)),e.originalEvent.deltaY<0&&(m.item.value-=m.item.step,m.item.value<m.item.min&&(m.item.value=m.item.min)),m.valueChanged(0)},m.active=!1,m.mdown=function(){m.active=!0},m.menter=function(){m.active=!0},m.mleave=function(){m.active=!1},m.mchange=function(){m.active=!1,m.valueChanged(0)},m.mup=function(){m.active&&(m.active=!1,m.valueChanged(0))}}},m.valueChanged=function(e){n({id:m.item.id,value:m.item.value},"number"==typeof e?e:10)},m.keyPressed=function(e){13===e.charCode||13===e.which?(u.emit({id:m.item.id,value:m.item.value}),m.lastItemSent=m.item.value):"blur"===e.type&&m.item.value!==m.lastItemSent&&(u.emit({id:m.item.id,value:m.item.value}),m.lastItemSent=m.item.value)};var n=function(e,t){0!==t?(i&&clearTimeout(i),i=setTimeout(function(){i=void 0,u.emit(e)},t)):u.emit(e)},o=function(e){e&&e.isOptionsValid&&(m.item.options=e.newOptions,delete m.item.isOptionsValid,delete m.item.newOptions)}}}]);
angular.module("ui").run(["$templateCache",function(e){e.put("logout.html",'<head></head> <body> <script src="js/app.min.js"><\/script> <script> for (var key in localStorage) {\n    if (localStorage.hasOwnProperty(key)) {\n        if (key.indexOf("nr-") === 0) {\n            localStorage.removeItem(key);\n        }\n    }\n}\n$.ajax({\n    type: "GET",\n    url: window.location.href,\n    async: true,\n    username: "some_non_user_name",\n    password: "a_not_valid_password"\n})\n.done(function() { alert(\'Error!\') })\n.fail(function() {\n    var url = window.location.href.split("logout")[0];\n    setTimeout(function() { window.location.href = url; }, 1000);\n}); <\/script> <style> div {\n    width: 400px;\n    height: 300px;\n    position: absolute;\n    top:0;\n    bottom: 0;\n    left: 0;\n    right: 0;\n    margin: auto;\n    font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen-Sans, Ubuntu, Cantarell, Helvetica Neue, sans-serif;\n} </style> <div class="node-red-ui--notabs"> <table><tr><td><center><a href="./"><img src="icon120x120.png"></a></center></td></tr> <tr><td><center><h2>Welcome to the Node-RED Dashboard</h2></center></td></tr> <tr><td><center>Please <a href="./">sign in</a> to see your flow.</center></td></tr></table> </div> </body> '),e.put("partials/main.html",'<md-toolbar ng-show="main.hideToolbar !== true" id="toolbar"> <div class="md-toolbar-tools" id="nr-dashboard-toolbar"> <md-button ng-show="!(main.lockMenu != \'false\') && main.len > 1" ng-click="main.toggleSidenav()" class="md-icon-button" aria-label="menu button"> <ng-md-icon icon="menu"></ng-md-icon> </md-button> <h1 ng-show="main.len <= 1" style="width:30px"> </h1> <h1 ng-show="main.lockMenu != \'false\'" node-id="{{main.id}}">{{main.name}}</h1> <h1 ng-show="!(main.lockMenu != \'false\') && main.loaded" node-id="{{main.selectedTab.id}}">{{main.selectedTab.header || main.selectedTab.name}}</h1> </div> </md-toolbar> <section layout="row" flex> <md-sidenav ng-hide="main.len <= 1" class="md-sidenav-left" md-component-id="left" md-is-locked-open="(main.lockMenu != \'false\')"> <md-list> <md-list-item ng-repeat="obj in main.menu" ng-class="{\'nr-menu-item-active\':location.$$path==\'/\'+$index}" ng-disabled="obj.disabled" ng-if="!obj.hidden" ng-click="main.open(obj, $index)"> <ui-icon icon="{{obj.icon}}" style="margin:5px"></ui-icon> <p style="margin-right:12px; min-width:120px;" ng-show="(main.lockMenu != \'icon\')">{{main.getMenuName(obj)}}</p> </md-list-item> </md-list> </md-sidenav> <md-content flex> <div ui-masonry ng-show="main.selectedTab.header" id="{{\'Tab_\'+main.selectedTab.header | spaceToUnderscore}}"> <ui-card-panel node-id="{{group.header.id}}" ng-repeat="group in main.selectedTab.items" id="{{main.selectedTab.header+\'_\'+group.header.name | spaceToUnderscore}}" ng-if="group.header && group.header.config && !group.header.config.hidden"> <ui-component ng-repeat="control in group.items" item="control"></ui-component> </ui-card-panel> </div> <div class="node-red-ui--inline-link" ng-show="!main.selectedTab.header"> <iframe class="iframe" ng-src="{{ main.selectedTab.link }}" allowfullscreen></iframe> \x3c!-- <div>The url {{ }} cannot be loaded into an iframe.</div> --\x3e </div> </md-content> </section> <div id="nr-dashboard-footer" layout="row"></div> '),e.put("partials/toast.html",'<md-toast layout="column" style="border:4px solid {{::toast.highlight}}; padding:0px; transition:border-color 0.1s;"> <div> <h3 ng-if="toast.title">{{::toast.title}}</h3> <h4 flex ng-bind-html="::toast.message | trusted"></h4> </div> </md-toast> '),e.put("components/ui-card-panel/ui-card-panel.html",'<div layout="column" class="nr-dashboard-cardpanel" ng-class="[group.header.config && group.header.config.className]" node-classname="{{group.header.config.className}}"> <p class="nr-dashboard-cardtitle" ng-style="{width:ctrl.width-12}" ng-if="group.header && group.header.config.disp && group.header[group.header.length-1]!=\'!\'">{{group.header.name}} <span ng-if="group.header.config.collapse" ng-model="collapsed" ng-click="collapseCard()" class="nr-dashboard-cardcarat"> <i ng-class="{ \'fa fa-caret-down\':collapsed, \'fa fa-caret-up\':!collapsed }"></i> </span> </p> <div class="nr-dashboard-cardcontainer" id="{{main.selectedTab.header+\'_\'+group.header.name | spaceToUnderscore}}_cards" ng-transclude ng-style="{width:ctrl.width, height:ctrl.height}"></div> </div> '),e.put("components/ui-chart-js/ui-chart-js.html",'<div> <canvas ng-if="me.item.look===\'line\'" class="chart chart-line" chart-data="config.data" chart-series="config.series" chart-labels="config.labels" chart-options="config.options" chart-dataset-override="config.overrides" chart-colors="config.colours"> </canvas> <canvas ng-if="me.item.look===\'bar\'" class="chart chart-bar" chart-data="config.data" chart-series="config.series" chart-labels="config.labels" chart-options="config.options" chart-dataset-override="config.overrides" chart-colors="config.colours"> </canvas> <canvas ng-if="me.item.look===\'horizontalBar\'" class="chart chart-horizontalBar" chart-data="config.data" chart-series="config.series" chart-labels="config.labels" chart-options="config.options" chart-dataset-override="config.overrides" chart-colors="config.colours"> </canvas> <canvas ng-if="me.item.look===\'pie\'" class="chart chart-pie" chart-data="config.data" chart-series="config.series" chart-labels="config.labels" chart-options="config.options" chart-dataset-override="config.overrides" chart-colors="config.colours"> </canvas> <canvas ng-if="me.item.look===\'polar-area\'" class="chart chart-polar-area" chart-data="config.data" chart-series="config.series" chart-labels="config.labels" chart-options="config.options" chart-dataset-override="config.overrides" chart-colors="config.colours"> </canvas> <canvas ng-if="me.item.look===\'radar\'" class="chart chart-radar" chart-data="config.data" chart-series="config.series" chart-labels="config.labels" chart-options="config.options" chart-dataset-override="config.overrides" chart-colors="config.colours"> </canvas> </div> '),e.put("components/ui-gauge/ui-gauge.html","<div id=\"gauge_{{$id}}\" style=\"width:{{0.95 * me.item.width * me.item.sizes.sx - (20 * (me.item.gtype === 'compass')) }}px;\n    height:{{0.95 * (me.item.height * me.item.sizes.sy)+((me.item.title.length == 0) * me.item.sizes.sy) - (20 * (me.item.gtype === 'compass')) }}px;\n    margin-top:-20px;\n    padding-bottom:{{(me.item.gtype === 'wave') * 6}}px;\"> </div> "),e.put("components/ui-icon/ui-icon.html",'<ng-md-icon ng-if="iconType===\'angular-material\'" icon="{{icon}}"></ng-md-icon> <div ng-if="iconType===\'fa\'" style="display:inline-block; margin:auto; line-height:initial;"><i class="fa fa-fw" ng-class="icon"></i></div> <div ng-if="iconType===\'wi\'" style="display:inline-block; margin:auto; line-height:initial;"><i class="wi wi-fw" ng-class="icon"></i></div> <div ng-if="iconType===\'mi\'" style="display:inline-block; margin:auto; line-height:initial;"><i class="material-icons" ng-class="icon">{{icon.substr(3)}}</i></div> <div ng-if="iconType===\'icofont\'" style="display:inline-block; margin:auto; line-height:initial;"><i class="icofont icofont-fw" ng-class="icon"></i></div> <div ng-if="iconType===\'iconify\'" style="display:inline-block; margin:auto; line-height:18px; vertical-align:middle;" class="{{icon.split(\' \')[0].substr(8)}}"><i class="iconify" data-icon="{{icon.split(\' \')[0].substr(8)}}" data-width="{{icon.split(\' \')[1] || \'1.3em\'}}" data-height="{{icon.split(\' \')[1] || \'1.3em\'}}" data-inline="true" ng-class="icon"></i></div> <div ng-if="iconType===\'iconify1\'" style="display:inline-block; margin:auto; line-height:18px; vertical-align:middle;" class="{{icon.split(\' \')[0].substr(8)}}"><i class="iconify" data-icon="{{icon.split(\' \')[0].substr(8)}}" data-width="{{icon.split(\' \')[1] || \'1.3em\'}}" data-height="{{icon.split(\' \')[1] || \'1.3em\'}}" data-inline="true" ng-class="icon"></i></div> <img ng-if="iconType===\'image\'" ng-src="{{url}}" style="width:24px; display:block; margin:auto; line-height:initial;"> '),e.put("components/ui-component/templates/button.html",'<md-card ui-card-size="{{ me.item.width }}x{{ me.item.height }}" class="nr-dashboard-button" node-class="{{ me.item.className }}" ng-class="[{\'nr-dashboard-disabled\':me.item.disabled}, me.item.className]" node-id="{{me.item.id}}"> <md-button class="md-raised" ng-click="me.buttonClick($event)" ng-disabled="me.item.disabled" aria-label="{{\'button\' + me.item.label}}" ng-style="{\'background-color\':me.item.getText(), \'color\':me.item.getColor(), \'z-index\':1, \'padding\':\'0px\'}"> <ui-icon ng-show="me.item.icon.length" icon="{{me.item.getIcon()}}" ng-style="{color:me.item.getColor()}"> </ui-icon> <span ng-bind-html="me.item.getLabel()"></span> <md-tooltip ng-if="me.item.getTooltip().length" md-delay="700" md-direction="bottom" ng-bind-html="me.item.getTooltip()"> </md-tooltip> </md-button> </md-card> '),e.put("components/ui-component/templates/chart.html",'<md-card ui-card-size="{{ me.item.width }}x{{ me.item.height }}" layout-align="center center" ng-class="[{\'nr-dashboard-disabled\':me.item.disabled}, me.item.className]" node-id="{{me.item.id}}"> <div class="nr-dashboard-chart-container" style="width:100%; height:100%;"> <p class="label nr-dashboard-chart-title" ng-class="{\'nr-dashboard-chart-titlel\':(me.item.width > 3)}" ng-bind-html="me.item.getLabel()"> </p> <ui-chart-js class="nr-dashboard-chart" ng-class="{\'nr-dashboard-chart-nolabel\':me.item.getLabel() == \'\'}" ng-swipe-right="$event.stopPropagation();" ng-swipe-left="$event.stopPropagation();"> </ui-chart-js> <p class="blank-label" ng-if="config && config.nodata">{{ me.item.nodata }} </p> </div> </md-card> '),e.put("components/ui-component/templates/colour-picker.html",'<md-card ui-card-size="{{ me.item.width }}x{{ me.item.height }}" flex layout="row" layout-align="space-between center" class="nr-dashboard-colour-picker" ng-class="[{\'nr-dashboard-disabled\':me.item.disabled}, me.item.className]" node-id="{{me.item.id}}"> <p> <span ng-hide="(me.item.width < 2) || (me.item.width < 5 && (me.item.inline || me.item.textValue))" class="label" ng-bind-html="me.item.getLabel()"> </span> </p> <color-picker ng-model="me.item.value" aria-label="{{me.item.label}}" ng-attr-options="me.item.options" ng-attr-event-api="me.item.eventapi" ng-keypress="me.item.key($event)" ng-swipe-right="$event.stopPropagation();" ng-swipe-left="$event.stopPropagation();"> </color-picker> </md-card> '),e.put("components/ui-component/templates/date-picker.html",'<md-card ui-card-size="{{ me.item.width }}x{{ me.item.height }}" flex layout="row" layout-align="space-between center" class="nr-dashboard-date-picker" ng-class="[{\'nr-dashboard-disabled\':me.item.disabled}, me.item.className]" node-id="{{me.item.id}}"> <md-input-container flex layout="row"> <p class="nr-dashboard-date-picker-label" ng-if="me.item.label" ng-bind-html="me.item.getLabel()"> </p> <md-datepicker class="nr-dashboard-date-picker" md-placeholder="{{me.item.getLabel()}}" md-open-on-focus ng-model="me.item.ddd" ng-blur="me.setDate()"> </md-datepicker> </md-input-container> </md-card> '),e.put("components/ui-component/templates/dropdown.html",'<md-card ui-card-size="{{ me.item.width }}x{{ me.item.height }}" layout="row" layout-align="space-between center" class="nr-dashboard-dropdown" ng-class="[{\'nr-dashboard-disabled\':me.item.disabled}, me.item.className]" node-id="{{me.item.id}}"> <md-input-container flex layout="row"> <p ng-if="me.item.width>1 && me.item.getLabel().length>0" class="label" ng-if="me.item.label" ng-bind-html="me.item.getLabel()"> </p> <md-tooltip ng-if="me.item.getTooltip().length" md-delay="700" md-direction="bottom" ng-bind-html="me.item.getTooltip()"> </md-tooltip> <md-select ng-if="!me.item.multiple" ng-change="me.itemChanged()" ng-disabled="me.item.disabled" ng-model="me.item.value" placeholder="{{ me.item.place }}" flex="100"> <md-select-header ng-if="me.item.options.length > 7" class="nr-dashboard-dropdown-header"> <md-input-container class="md-block" style="height:32px;" flex> <input ng-model="me.searchTerm" ng-keydown="$event.stopPropagation();" ng-click="$event.stopPropagation();" type="search" aria-label="Filter"> <ng-md-icon icon="search"></ng-md-icon> </md-input-container> </md-select-header> <md-option ng-value="opt.value" ng-repeat="opt in me.item.options | filter: { label: me.searchTerm }">{{ opt.label }} </md-option> </md-select> <md-select ng-if="me.item.multiple" ng-change="me.itemChanged()" ng-disabled="me.item.disabled" md-on-close="me.closed()" multiple="multiple" ng-model="me.item.value" placeholder="{{ me.item.place }}" flex="100"> <md-select-header ng-if="me.item.options.length > 7" class="nr-dashboard-dropdown-header"> <md-checkbox md-no-ink aria-label="Select all" ng-model="me.selectAll" ng-change="me.checkAll()" style="width:unset;"></md-checkbox> <md-input-container class="md-block" style="height:32px;" flex> <input ng-model="me.searchTerm" ng-keydown="$event.stopPropagation()" type="search" aria-label="Filter"> <ng-md-icon icon="search"></ng-md-icon> </md-input-container> </md-select-header> <md-option ng-value="opt.value" ng-repeat="opt in me.item.options | filter: { label: me.searchTerm }">{{ opt.label }} </md-option> </md-select> </md-input-container> </md-card> '),e.put("components/ui-component/templates/form.html",'<md-card ui-card-size="{{me.item.width}}x{{(me.item.height > me.item.rowCount ? me.item.height : me.item.rowCount )}}" layout="row" layout-align="space-between center" class="nr-dashboard-form" ng-class="[{\'nr-dashboard-disabled\':me.item.disabled}, me.item.className]" node-id="{{me.item.id}}"> <form name="form" ng-submit="me.submit(form)" style="margin-top:{{(me.item.label ? 0 : me.item.rowCount < 3 ? me.item.rowHeight/6 : me.item.rowHeight/2.5)}}px"> <p class="formlabel" style="margin-bottom:{{(me.item.rowHeight/9)}}px" ng-if="me.item.label" ng-bind-html="me.item.getLabel()"></p> <div class="formElement" ng-class="{\'formElementSplit\':(me.item.splitLayout)}" layout-gt-sm="row" ng-repeat="opt in me.item.options track by $index"> <md-input-container class="md-block" style="height:{{(me.item.rowHeight * (opt.type==\'multiline\' ? opt.rows : 1)) }}px" flex> <label ng-if="(opt.type==\'text\' || opt.type==\'number\' || opt.type==\'email\' || opt.type==\'multiline\' || opt.type==\'password\' || opt.type==\'date\' || opt.type==\'time\') && opt.label">{{opt.label}}</label> <input ng-if="opt.type==\'text\' || opt.type==\'email\' || opt.type==\'password\'" type="{{opt.type}}" ng-model="me.item.formValue[opt.value]" ng-required="opt.required" ng-keydown="me.stop($event)"> <input ng-if="opt.type==\'date\'" type="{{opt.type}}" ng-model="me.item.formValue[opt.value]" ng-required="opt.required" ng-keydown="me.stop($event)" placeholder="yyyy-mm-dd"> <input ng-if="opt.type==\'time\'" type="{{opt.type}}" ng-model="me.item.formValue[opt.value]" ng-required="opt.required" ng-keydown="me.stop($event)" placeholder="HH:MM"> <input ng-if="opt.type==\'number\'" type="{{opt.type}}" ng-model="me.item.formValue[opt.value]" ng-required="opt.required" ng-keydown="me.stop($event)" step="any"> <textarea ng-if="opt.type==\'multiline\'" md-no-autogrow ng-required="opt.required" ng-model="me.item.formValue[opt.value]" style="height:{{(opt.rows * me.item.sy) - 10}}px; padding:10px 2px 1px 0;"></textarea> <md-switch ng-if="opt.type==\'switch\'" md-no-ink ng-model="me.item.formValue[opt.value]">{{opt.label}}</md-switch> <md-checkbox ng-if="opt.type==\'checkbox\'" md-no-ink aria-label="Checkbox No Ink" ng-model="me.item.formValue[opt.value]"> {{opt.label}}</md-checkbox> </md-input-container> \x3c!-- <md-datepicker ng-if="opt.type==\'date\'" ng-model="me.item.formValue[opt.value]"></md-datepicker> --\x3e </div> <div class="form-control" ng-class="{\'form-control-single\':me.item.cancel == \'\',\'form-control-no-label\':me.item.label == \'\'}" style="margin-top:{{( me.item.label ==\'\' ? me.item.rowCount < 3 ? me.item.rowHeight * 0.4 : me.item.rowHeight * 0.2 : me.item.rowHeight * -0.1)}}px;"> <md-button class="md-raised nr-dashboard-form-button" type="submit" style="height:{{(me.item.sy -4)}}px;line-height:{{(me.item.sy -4)}}px">{{me.item.submit}}</md-button> <md-button ng-if="me.item.cancel != \'\'" class="md-raised nr-dashboard-form-button" style="height:{{(me.item.sy -4)}}px;line-height:{{(me.item.sy -4)}}px" ng-click="me.reset()">{{me.item.cancel}}</md-button> </div> </form> </md-card> cancel'),e.put("components/ui-component/templates/gauge.html",'<md-card ui-card-size="{{ me.item.width }}x{{ me.item.height }}" layout-align="center center" ng-class="[{\'nr-dashboard-disabled\':me.item.disabled}, me.item.className]" node-id="{{me.item.id}}"> <p class="label nr-dashboard-gauge-title" ng-class="{\'nr-dashboard-gauge-titlel\':(me.item.width > 3)}" ng-bind-html="me.item.getLabel()" ng-hide="(me.item.height <= 2)"> </p> <p ng-show="(me.item.height == 2)" ng-bind-html="me.item.getLabel()" ng-class="{\'nr-dashboard-gauge-titlem\':(me.item.height == 2)}"> </p> <p ng-show="(me.item.height == 1)" ng-bind-html="me.item.getLabel()" ng-class="{\'nr-dashboard-gauge-titles\':(me.item.height == 1)}"> </p> <ui-gauge style="text-align:center;" class="nr-dashboard-gauge"> </ui-gauge> </md-card> '),e.put("components/ui-component/templates/numeric.html",'<md-card ui-card-size="{{ me.item.width }}x{{ me.item.height }}" flex layout="row" layout-align="space-between center" class="nr-dashboard-numeric" ng-class="[{\'nr-dashboard-disabled\':me.item.disabled}, me.item.className]" node-id="{{me.item.id}}"> <p class="label" ng-bind-html="me.item.getLabel()"> </p> <md-tooltip ng-if="me.item.getTooltip().length" md-delay="700" md-direction="bottom" ng-bind-html="me.item.getTooltip()"> </md-tooltip> <div layout="row" layout-align="center center"> <md-button class="md-icon-button down-button" aria-label="{{me.item.label}}" ng-mousedown="me.periodicChange(-me.item.step)" ng-mouseup="me.stopPeriodic()" ng-mouseleave="me.stopPeriodic()" style="z-index:1"> <ui-icon icon="expand_more"></ui-icon> </md-button> <center> <p ng-if="(me.item.ed === false)" class="value" style="min-width:{{me.item.minWidth}}px;" ng-bind-html="me.item.getText()"> </p> <span ng-if="(me.item.ed === true)"> <span class="value" ng-bind-html="me.item.pre"></span> <input ng-model="me.item.value" ng-change="me.newValue()" class="value" ng-disabled="me.item.disabled" style="max-width:{{me.item.minWidth}}px;"> <span class="value" ng-bind-html="me.item.post"></span> </span> </center> <md-button class="md-icon-button up-button" aria-label="{{me.item.label}}" ng-mousedown="me.periodicChange(me.item.step)" ng-mouseup="me.stopPeriodic()" ng-mouseleave="me.stopPeriodic()" style="z-index:1"> <ui-icon icon="expand_less"></ui-icon> </md-button> </div> </md-card> '),e.put("components/ui-component/templates/slider.html",'<md-card ui-card-size="{{ me.item.width }}x{{ me.item.height }}" flex layout="row" layout-align="space-between center" class="nr-dashboard-slider" ng-class="[{\'nr-dashboard-disabled\':me.item.disabled}, {\'nr-dashboard-slider-v\':(me.item.width < me.item.height)}, me.item.className]" ng-swipe-right="$event.stopPropagation();" ng-swipe-left="$event.stopPropagation();" node-id="{{me.item.id}}"> <p ng-show="{{me.item.width >= me.item.height}}" class="label" ng-bind-html="me.item.getLabel()"> </p> <md-tooltip ng-if="me.item.getTooltip().length" md-delay="700" md-direction="bottom" ng-bind-html="me.item.getTooltip()"> </md-tooltip> <md-slider ng-if="me.item.outs===\'all\'" flex="100" min="{{me.item.min}}" max="{{me.item.max}}" step="{{me.item.step}}" ng-model="me.item.value" aria-label="{{me.item.label}}" ng-change="me.valueChanged(10)" ng-on-wheel="me.wheel($event)" style="z-index:1; touch-action:none; min-width:32px;" ng-attr-md-vertical="{{ (me.item.width < me.item.height) || undefined}}" ng-attr-md-invert="{{ me.item.invert || undefined}}"> </md-slider> <md-slider ng-if="me.item.outs===\'end\'" md-discrete flex="100" min="{{me.item.min}}" max="{{me.item.max}}" step="{{me.item.step}}" ng-model="me.item.value" aria-label="{{me.item.label}}" ng-change="me.mchange()" ng-mouseup="me.mup()" ng-mouseleave="me.mleave()" ng-mouseenter="me.menter()" style="z-index:1; touch-action:none; min-width:32px;" ng-style="(me.item.width >= me.item.height) && {\'margin-top\':\'20px\'};" ng-attr-md-vertical="{{ (me.item.width < me.item.height) || undefined}}" ng-attr-md-invert="{{ me.item.invert || undefined}}"> </md-slider> <p ng-hide="{{me.item.width >= me.item.height}}" class="label-v" ng-bind-html="me.item.getLabel()"> </p> </md-card> '),e.put("components/ui-component/templates/spacer.html",'<md-card ui-card-size="{{ me.item.width }}x{{ me.item.height }}" layout="{{ me.item.layout }}" layout-align="{{ me.item.layoutAlign }}" class="nr-dashboard-spacer" ng-class="{\'nr-dashboard-disabled\':me.item.disabled}"> </md-card> '),e.put("components/ui-component/templates/switch.html",'<md-card ui-card-size="{{ me.item.width }}x{{ me.item.height }}" layout="row" layout-align="space-between center" class="nr-dashboard-switch" ng-click="me.switchClick()" ng-class="[{\'nr-dashboard-disabled\':me.item.disabled}, me.item.className]" node-id="{{me.item.id}}"> <p ng-if="me.item.label && (me.item.width !== 1)" class="label" ng-bind-html="me.item.getLabel()"> </p> <md-tooltip ng-if="me.item.getTooltip().length" md-delay="700" md-direction="bottom" ng-bind-html="me.item.getTooltip()"> </md-tooltip> <md-switch ng-model="me.item.value" ng-change="me.item.value = !me.item.value" ng-swipe-right="$event.stopPropagation();" ng-swipe-left="$event.stopPropagation();" aria-label="{{me.item.label}}" ng-class="{\'center\' : !me.item.label}" ng-if="!me.item.oncolor || !me.item.onicon || !me.item.offcolor || !me.item.officon" style="z-index:1"> </md-switch> <ui-icon icon="{{me.item.onicon}}" ng-style="{color: me.item.oncolor}" ng-class="{\'center\' : !me.item.label, \'ng-hide\': !me.item.value}" class="{{me.item.animate}}" ng-if="me.item.oncolor && me.item.onicon && me.item.offcolor && me.item.officon" style="z-index:1"> </ui-icon> <ui-icon icon="{{me.item.officon}}" ng-style="{color:me.item.offcolor}" ng-class="{\'center\' : !me.item.label, \'ng-hide\': me.item.value}" class="{{me.item.animate}}" ng-if="me.item.oncolor && me.item.onicon && me.item.offcolor && me.item.officon" style="z-index:1"> </ui-icon> </md-card> '),e.put("components/ui-component/templates/template.html",'<md-card ui-template="me.item.format" ui-card-size="{{ me.item.width }}x{{ me.item.height }}" class="nr-dashboard-template {{ me.item.class }}" ng-class="[{\'nr-dashboard-disabled\':me.item.disabled}, me.item.className]" ng-show="{{me.item.height >= 0}}" node-id="{{me.item.id}}"> </md-card> '),e.put("components/ui-component/templates/text-input-CR.html",'<md-card ui-card-size="{{ me.item.width }}x{{ me.item.height }}" layout="row" layout-align="space-between center" class="nr-dashboard-textinput" ng-class="[{\'nr-dashboard-disabled\':me.item.disabled}, me.item.className]" node-id="{{me.item.id}}"> <md-input-container class="md-block" flex md-is-error="false" ng-class="{\'has-label\':me.item.label}"> <label ng-bind-html="me.item.getLabel()"></label> <md-tooltip ng-if="me.item.getTooltip().length" md-delay="700" md-direction="bottom" ng-bind-html="me.item.getTooltip()"> </md-tooltip> <input ng-model="me.item.value" ng-model-options="{\'timezone\':\'UTC\'}" ng-keydown="me.keyPressed($event)" ng-blur="me.item.sendOnBlur ? me.keyPressed($event) : false" ng-trim="false" ng-disabled="me.item.disabled" aria-label="{{me.item.label}}" type="{{me.item.mode}}" style="z-index:1" step="any"> </md-input-container> </md-card> '),e.put("components/ui-component/templates/text-input.html",'<md-card ui-card-size="{{ me.item.width }}x{{ me.item.height }}" layout="row" layout-align="space-between center" class="nr-dashboard-textinput" ng-class="[{\'nr-dashboard-disabled\':me.item.disabled}, me.item.className]" node-id="{{me.item.id}}"> <md-input-container class="md-block" flex md-is-error="false" ng-class="{\'has-label\':me.item.label}"> <label ng-bind-html="me.item.getLabel()"></label> <md-tooltip ng-if="me.item.getTooltip().length" md-delay="700" md-direction="bottom" ng-bind-html="me.item.getTooltip()"> </md-tooltip> <input ng-model="me.item.value" ng-model-options="{\'timezone\':\'UTC\'}" ng-change="me.valueChanged({{me.item.delay}})" ng-trim="false" ng-disabled="me.item.disabled" aria-label="{{me.item.label}}" type="{{me.item.mode}}" style="z-index:1" ng-style="(me.item.mode===\'color\') && {\'padding-left\':\'25%\'}" step="any"> </md-input-container> </md-card> '),e.put("components/ui-component/templates/text.html",'<md-card ui-card-size="{{ me.item.width }}x{{ me.item.height }}" layout="{{ me.item.layout }}" layout-align="{{ me.item.layoutAlign }}" class="nr-dashboard-text" ng-class="[ me.item.safeLabel, {\'nr-dashboard-disabled\':me.item.disabled}, me.item.className]" node-id="{{me.item.id}}"> <p class="label" ng-bind-html="me.item.getLabel()"></p> <p class="value" ng-bind-html="me.item.getText()"></p> </md-card> ')}]);
    "version": "3.1.8",
                me.item.getText = $interpolate(me.item.format).bind(null, me.item);
                me.item.getLabel = $interpolate(me.item.label).bind(null, me.item);
                me.item.safeLabel = "nr-dashboard-widget-" + (me.item.label).replace(/\W/g,'_');
                me.item.getTooltip = $interpolate(me.item.tooltip).bind(null, me.item);
                me.item.getColor = $interpolate(me.item.color).bind(null, me.item);
                me.item.getIcon = $interpolate(me.item.icon).bind(null, me.item);
                me.item.getUnits = $interpolate(me.item.units).bind(null, me.item);

Fixed code:
### 3.1.9: Maintenance Release

 - Fix Cross site scripting for ui_text format input. Issue #772

# Time: Wed Aug 24 2022 17:30:31 GMT+0100 (British Summer Time)
# hash: 9ff936fabba7ec5170a4f63f8f6b72aa1343c36c57f8382848eb81dae9ca5512
angular.module("ui").controller("uiComponentController",["$scope","UiEvents","$interpolate","$interval",function(l,u,e,r){this.$onInit=function(){var i,a=this;"string"==typeof a.item.format&&(-1===a.item.format.indexOf("constructor")?a.item.getText=e(a.item.format).bind(null,a.item):a.item.getText=function(){return a.item.format}),"string"==typeof a.item.label&&(-1===a.item.label.indexOf("constructor")?(a.item.getLabel=e(a.item.label).bind(null,a.item),a.item.safeLabel="nr-dashboard-widget-"+a.item.label.replace(/\W/g,"_")):a.item.getText=function(){return a.item.label}),"string"==typeof a.item.tooltip&&(-1===a.item.tooltip.indexOf("constructor")?a.item.getTooltip=e(a.item.tooltip).bind(null,a.item):a.item.getText=function(){return a.item.tooltip}),"string"==typeof a.item.color&&(-1===a.item.color.indexOf("constructor")?a.item.getColor=e(a.item.color).bind(null,a.item):a.item.getText=function(){return a.item.color}),"string"==typeof a.item.icon&&(-1===a.item.icon.indexOf("constructor")?a.item.getIcon=e(a.item.icon).bind(null,a.item):a.item.getText=function(){return a.item.icon}),"string"==typeof a.item.units&&(-1===a.item.units.indexOf("constructor")?a.item.getUnits=e(a.item.units).bind(null,a.item):a.item.getText=function(){return a.item.units}),a.init=function(){switch(a.item.type){case"button":a.buttonClick=function(e){m({id:a.item.id,value:a.item.value,event:{clientX:e.originalEvent.clientX,clientY:e.originalEvent.clientY,bbox:[e.originalEvent.clientX-e.originalEvent.layerX,e.originalEvent.clientY-e.originalEvent.layerY+e.currentTarget.clientHeight,e.originalEvent.clientX-e.originalEvent.layerX+e.currentTarget.clientWidth,e.originalEvent.clientY-e.originalEvent.layerY]}},0)};break;case"switch":a.switchClick=function(){m({id:a.item.id,value:!a.item.value},0)};break;case"dropdown":a.searchTerm="",a.selectAll=!1,a.changed=!1,a.itemChanged=function(){a.searchTerm="",a.item.multiple?a.changed=!0:a.valueChanged(0)},a.checkAll=function(){var e=a.item.options.filter(function(e){return e.label.toLowerCase().includes(a.searchTerm.toLowerCase())});a.item.value=a.selectAll?e.map(function(e){return e.value}):[],a.valueChanged(0)},a.closed=function(){a.changed&&(a.changed=!1,a.valueChanged(0))},(a.item.me=a).processInput=function(e){o(e)};break;case"numeric":var i=function(e){a.item.value=parseFloat(a.item.value),isNaN(a.item.value)&&(a.item.value=a.item.min),0<e?(a.item.value==a.item.max&&1==a.item.wrap?a.item.value=a.item.min:a.item.value<a.item.max&&(a.item.value=Math.round(1e4*Math.min(a.item.value+e,a.item.max))/1e4),a.item.value<a.item.min&&(a.item.value=a.item.min)):e<0&&(a.item.value==a.item.min&&1==a.item.wrap?a.item.value=a.item.max:a.item.value>a.item.min&&(a.item.value=Math.round(1e4*Math.max(a.item.value+e,a.item.min))/1e4),a.item.value>a.item.max&&(a.item.value=a.item.max))},e=9.5*(Math.round(1e4*(a.item.min+a.item.step))/1e4).toString().length,t=9.5*(Math.round(1e4*(a.item.max+a.item.step))/1e4).toString().length;a.item.minWidth=t<e?e:t;var n=null;a.newValue=function(){isNaN(parseFloat(a.item.value))||(a.item.value<a.item.min&&(a.item.value=a.item.min),a.item.value>a.item.max&&(a.item.value=a.item.max),u.emit({id:a.item.id,value:a.item.value}))},a.periodicChange=function(e){i(e);var t=0;n=r(function(){75<++t?i(250*e):50<t?i(50*e):35<t?i(10*e):25<t?i(2*e):15<t?i(e):5<t&&t%2&&i(e)},100)},a.stopPeriodic=function(){n&&(r.cancel(n),n=null,a.valueChanged(0))};break;case"chart":a.item.theme=l.main.selectedTab.theme;break;case"colour-picker":(a.item.width<4||!a.item.showValue&&!a.item.showPicker)&&(a.item.showPicker=!1,a.item.showValue=!1,a.item.showSwatch=!0),a.item.showPicker&&a.item.height<4&&(a.item.height=a.item.showSwatch||a.item.showValue?4:3),a.item.options={format:a.item.format,inline:a.item.showPicker,hue:a.item.showHue,alpha:a.item.showAlpha,lightness:a.item.showLightness,swatch:a.item.showSwatch,swatchOnly:a.item.width<2||!a.item.showValue,swatchPos:"right",pos:"bottom right",case:"lower",round:!a.item.square,pickerOnly:a.item.showPicker&&!(a.item.showSwatch||a.item.showValue)},a.item.key=function(e){13!==e.charCode&&13!==e.which&&9!==e.charCode&&9!==e.which||(u.emit({id:a.item.id,value:a.item.value}),a.api&&a.api.close())},a.item.eventapi={onChange:function(e,t,i){void 0!==i&&a.valueChanged(0)},onOpen:function(e,t){a.api=e}},l.$watch("me.item.value",function(){a.item.oldValue||(a.item.oldValue=a.item.value),"true"===a.item.dynOutput&&a.item.value!==a.item.oldValue&&(a.item.oldValue=a.item.value,a.valueChanged(20))});break;case"text-input":case"text-input-CR":-1!=a.item.mode.indexOf("time")&&(a.processInput=function(e){var t=new Date(e.value);if(isNaN(e.value)){var i=e.value.match(/^(\d\d):(\d\d)/);if(null==i){var n=Date.parse(e.value);isNaN(n)&&(n=Date.now()),t=new Date(n)}else t=new Date("1970-01-01 "+i[1]+":"+i[2]+":00Z")}t.setMilliseconds(0),t.setSeconds(0),e.value=t,a.item.value=e.value},a.item.me=a),"week"!==a.item.mode&&"month"!==a.item.mode||(a.processInput=function(e){var t=new Date(e.value);if(isNaN(e.value)){var i=Date.parse(e.value);isNaN(i)&&(i=Date.now()),t=new Date(i)}t.setMilliseconds(0),t.setSeconds(0),e.value=t,a.item.value=e.value},a.item.me=a);break;case"date-picker":void 0!==a.item.ddd&&("number"!=typeof a.item.ddd&&"string"!=typeof a.item.ddd||(a.item.ddd=new Date(a.item.ddd))),a.processInput=function(e){e.value=new Date(e.value),a.item.ddd=e.value},a.setDate=function(){a.item.value=a.item.ddd,a.valueChanged(0)},a.item.me=a;break;case"form":a.processInput=function(e){if("object"==typeof e.value)for(var t in e.value)if(a.item.formValue.hasOwnProperty(t))for(var i in a.item.options)"date"!==a.item.options[i].type&&"time"!==a.item.options[i].type||a.item.options[i].value!==t||(e.value[t]=new Date(e.value[t])),a.item.formValue[t]=e.value[t]},a.item.extraRows=0,a.item.options.map(function(e){"multiline"==e.type&&1<e.rows&&(a.item.extraRows+=e.rows-1)}),a.item.rowCount=1==a.item.splitLayout?Math.ceil(a.item.options.length/2):a.item.options.length,a.item.rowCount+=""==a.item.label?1:2,a.item.rowCount+=a.item.extraRows,a.item.rowHeight=((a.item.rowCount-1)*a.item.sy+(""==a.item.label?.3*a.item.sy:1.2*a.item.sy)+(a.item.rowCount-1)*a.item.cy)/a.item.rowCount,a.stop=function(e){13!==e.charCode&&13!==e.which||(e.preventDefault(),e.stopPropagation())},a.submit=function(){a.item.value=JSON.parse(JSON.stringify(a.item.formValue)),a.valueChanged(0),a.reset()},a.reset=function(){for(var e in a.item.options)"checkbox"===a.item.options[e].type||"switch"===a.item.options[e].type?a.item.formValue[a.item.options[e].value]=!1:a.item.formValue[a.item.options[e].value]="";l.$$childTail.form.$setUntouched(),l.$$childTail.form.$setPristine()},a.item.me=a;break;case"template":a.setFormat=function(e){a.item.format=e},void 0!==a.item.msg&&void 0!==a.item.msg.template&&a.setFormat(a.item.msg.template);break;case"slider":a.wheel=function(e){e.preventDefault(),0<e.originalEvent.deltaY&&(a.item.value+=a.item.step,a.item.value>a.item.max&&(a.item.value=a.item.max)),e.originalEvent.deltaY<0&&(a.item.value-=a.item.step,a.item.value<a.item.min&&(a.item.value=a.item.min)),a.valueChanged(0)},a.active=!1,a.mdown=function(){a.active=!0},a.menter=function(){a.active=!0},a.mleave=function(){a.active=!1},a.mchange=function(){a.active=!1,a.valueChanged(0)},a.mup=function(){a.active&&(a.active=!1,a.valueChanged(0))}}},a.valueChanged=function(e){m({id:a.item.id,value:a.item.value},"number"==typeof e?e:10)},a.keyPressed=function(e){13===e.charCode||13===e.which?(u.emit({id:a.item.id,value:a.item.value}),a.lastItemSent=a.item.value):"blur"===e.type&&a.item.value!==a.lastItemSent&&(u.emit({id:a.item.id,value:a.item.value}),a.lastItemSent=a.item.value)};var m=function(e,t){0!==t?(i&&clearTimeout(i),i=setTimeout(function(){i=void 0,u.emit(e)},t)):u.emit(e)},o=function(e){e&&e.isOptionsValid&&(a.item.options=e.newOptions,delete a.item.isOptionsValid,delete a.item.newOptions)}}}]);
angular.module("ui").run(["$templateCache",function(e){e.put("logout.html",'<head></head> <body> <script src="js/app.min.js"><\/script> <script> for (var key in localStorage) {\n    if (localStorage.hasOwnProperty(key)) {\n        if (key.indexOf("nr-") === 0) {\n            localStorage.removeItem(key);\n        }\n    }\n}\n$.ajax({\n    type: "GET",\n    url: window.location.href,\n    async: true,\n    username: "some_non_user_name",\n    password: "a_not_valid_password"\n})\n.done(function() { alert(\'Error!\') })\n.fail(function() {\n    var url = window.location.href.split("logout")[0];\n    setTimeout(function() { window.location.href = url; }, 1000);\n}); <\/script> <style> div {\n    width: 400px;\n    height: 300px;\n    position: absolute;\n    top:0;\n    bottom: 0;\n    left: 0;\n    right: 0;\n    margin: auto;\n    font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen-Sans, Ubuntu, Cantarell, Helvetica Neue, sans-serif;\n} </style> <div class="node-red-ui--notabs"> <table><tr><td><center><a href="./"><img src="icon120x120.png"></a></center></td></tr> <tr><td><center><h2>Welcome to the Node-RED Dashboard</h2></center></td></tr> <tr><td><center>Please <a href="./">sign in</a> to see your flow.</center></td></tr></table> </div> </body> '),e.put("partials/main.html",'<md-toolbar ng-show="main.hideToolbar !== true" id="toolbar"> <div class="md-toolbar-tools" id="nr-dashboard-toolbar"> <md-button ng-show="!(main.lockMenu != \'false\') && main.len > 1" ng-click="main.toggleSidenav()" class="md-icon-button" aria-label="menu button"> <ng-md-icon icon="menu"></ng-md-icon> </md-button> <h1 ng-show="main.len <= 1" style="width:30px"> </h1> <h1 ng-show="main.lockMenu != \'false\'" node-id="{{main.id}}">{{main.name}}</h1> <h1 ng-show="!(main.lockMenu != \'false\') && main.loaded" node-id="{{main.selectedTab.id}}">{{main.selectedTab.header || main.selectedTab.name}}</h1> </div> </md-toolbar> <section layout="row" flex> <md-sidenav ng-hide="main.len <= 1" class="md-sidenav-left" md-component-id="left" md-is-locked-open="(main.lockMenu != \'false\')"> <md-list> <md-list-item ng-repeat="obj in main.menu" ng-class="{\'nr-menu-item-active\':location.$$path==\'/\'+$index}" ng-disabled="obj.disabled" ng-if="!obj.hidden" ng-click="main.open(obj, $index)"> <ui-icon icon="{{obj.icon}}" style="margin:5px"></ui-icon> <p style="margin-right:12px; min-width:120px;" ng-show="(main.lockMenu != \'icon\')">{{main.getMenuName(obj)}}</p> </md-list-item> </md-list> </md-sidenav> <md-content flex> <div ui-masonry ng-show="main.selectedTab.header" id="{{\'Tab_\'+main.selectedTab.header | spaceToUnderscore}}"> <ui-card-panel node-id="{{group.header.id}}" ng-repeat="group in main.selectedTab.items" id="{{main.selectedTab.header+\'_\'+group.header.name | spaceToUnderscore}}" ng-if="group.header && group.header.config && !group.header.config.hidden"> <ui-component ng-repeat="control in group.items" item="control"></ui-component> </ui-card-panel> </div> <div class="node-red-ui--inline-link" ng-show="!main.selectedTab.header"> <iframe class="iframe" ng-src="{{ main.selectedTab.link }}" allowfullscreen></iframe> \x3c!-- <div>The url {{ }} cannot be loaded into an iframe.</div> --\x3e </div> </md-content> </section> <div id="nr-dashboard-footer" layout="row"></div> '),e.put("partials/toast.html",'<md-toast layout="column" style="border:4px solid {{::toast.highlight}}; padding:0px; transition:border-color 0.1s;"> <div> <h3 ng-if="toast.title">{{::toast.title}}</h3> <h4 flex ng-bind-html="::toast.message | trusted"></h4> </div> </md-toast> '),e.put("components/ui-card-panel/ui-card-panel.html",'<div layout="column" class="nr-dashboard-cardpanel" ng-class="[group.header.config && group.header.config.className]" node-classname="{{group.header.config.className}}"> <p class="nr-dashboard-cardtitle" ng-style="{width:ctrl.width-12}" ng-if="group.header && group.header.config.disp && group.header[group.header.length-1]!=\'!\'">{{group.header.name}} <span ng-if="group.header.config.collapse" ng-model="collapsed" ng-click="collapseCard()" class="nr-dashboard-cardcarat"> <i ng-class="{ \'fa fa-caret-down\':collapsed, \'fa fa-caret-up\':!collapsed }"></i> </span> </p> <div class="nr-dashboard-cardcontainer" id="{{main.selectedTab.header+\'_\'+group.header.name | spaceToUnderscore}}_cards" ng-transclude ng-style="{width:ctrl.width, height:ctrl.height}"></div> </div> '),e.put("components/ui-chart-js/ui-chart-js.html",'<div> <canvas ng-if="me.item.look===\'line\'" class="chart chart-line" chart-data="config.data" chart-series="config.series" chart-labels="config.labels" chart-options="config.options" chart-dataset-override="config.overrides" chart-colors="config.colours"> </canvas> <canvas ng-if="me.item.look===\'bar\'" class="chart chart-bar" chart-data="config.data" chart-series="config.series" chart-labels="config.labels" chart-options="config.options" chart-dataset-override="config.overrides" chart-colors="config.colours"> </canvas> <canvas ng-if="me.item.look===\'horizontalBar\'" class="chart chart-horizontalBar" chart-data="config.data" chart-series="config.series" chart-labels="config.labels" chart-options="config.options" chart-dataset-override="config.overrides" chart-colors="config.colours"> </canvas> <canvas ng-if="me.item.look===\'pie\'" class="chart chart-pie" chart-data="config.data" chart-series="config.series" chart-labels="config.labels" chart-options="config.options" chart-dataset-override="config.overrides" chart-colors="config.colours"> </canvas> <canvas ng-if="me.item.look===\'polar-area\'" class="chart chart-polar-area" chart-data="config.data" chart-series="config.series" chart-labels="config.labels" chart-options="config.options" chart-dataset-override="config.overrides" chart-colors="config.colours"> </canvas> <canvas ng-if="me.item.look===\'radar\'" class="chart chart-radar" chart-data="config.data" chart-series="config.series" chart-labels="config.labels" chart-options="config.options" chart-dataset-override="config.overrides" chart-colors="config.colours"> </canvas> </div> '),e.put("components/ui-gauge/ui-gauge.html","<div id=\"gauge_{{$id}}\" style=\"width:{{0.95 * me.item.width * me.item.sizes.sx - (20 * (me.item.gtype === 'compass')) }}px;\n    height:{{0.95 * (me.item.height * me.item.sizes.sy)+((me.item.title.length == 0) * me.item.sizes.sy) - (20 * (me.item.gtype === 'compass')) }}px;\n    margin-top:-20px;\n    padding-bottom:{{(me.item.gtype === 'wave') * 6}}px;\"> </div> "),e.put("components/ui-icon/ui-icon.html",'<ng-md-icon ng-if="iconType===\'angular-material\'" icon="{{icon}}"></ng-md-icon> <div ng-if="iconType===\'fa\'" style="display:inline-block; margin:auto; line-height:initial;"><i class="fa fa-fw" ng-class="icon"></i></div> <div ng-if="iconType===\'wi\'" style="display:inline-block; margin:auto; line-height:initial;"><i class="wi wi-fw" ng-class="icon"></i></div> <div ng-if="iconType===\'mi\'" style="display:inline-block; margin:auto; line-height:initial;"><i class="material-icons" ng-class="icon">{{icon.substr(3)}}</i></div> <div ng-if="iconType===\'icofont\'" style="display:inline-block; margin:auto; line-height:initial;"><i class="icofont icofont-fw" ng-class="icon"></i></div> <div ng-if="iconType===\'iconify\'" style="display:inline-block; margin:auto; line-height:18px; vertical-align:middle;" class="{{icon.split(\' \')[0].substr(8)}}"><i class="iconify" data-icon="{{icon.split(\' \')[0].substr(8)}}" data-width="{{icon.split(\' \')[1] || \'1.3em\'}}" data-height="{{icon.split(\' \')[1] || \'1.3em\'}}" data-inline="true" ng-class="icon"></i></div> <div ng-if="iconType===\'iconify1\'" style="display:inline-block; margin:auto; line-height:18px; vertical-align:middle;" class="{{icon.split(\' \')[0].substr(8)}}"><i class="iconify" data-icon="{{icon.split(\' \')[0].substr(8)}}" data-width="{{icon.split(\' \')[1] || \'1.3em\'}}" data-height="{{icon.split(\' \')[1] || \'1.3em\'}}" data-inline="true" ng-class="icon"></i></div> <img ng-if="iconType===\'image\'" ng-src="{{url}}" style="width:24px; display:block; margin:auto; line-height:initial;"> '),e.put("components/ui-component/templates/button.html",'<md-card ui-card-size="{{ me.item.width }}x{{ me.item.height }}" class="nr-dashboard-button" node-class="{{ me.item.className }}" ng-class="[{\'nr-dashboard-disabled\':me.item.disabled}, me.item.className]" node-id="{{me.item.id}}"> <md-button class="md-raised" ng-click="me.buttonClick($event)" ng-disabled="me.item.disabled" aria-label="{{\'button\' + me.item.label}}" ng-style="{\'background-color\':me.item.getText(), \'color\':me.item.getColor(), \'z-index\':1, \'padding\':\'0px\'}"> <ui-icon ng-show="me.item.icon.length" icon="{{me.item.getIcon()}}" ng-style="{color:me.item.getColor()}"> </ui-icon> <span ng-bind-html="me.item.getLabel()"></span> <md-tooltip ng-if="me.item.getTooltip().length" md-delay="700" md-direction="bottom" ng-bind-html="me.item.getTooltip()"> </md-tooltip> </md-button> </md-card> '),e.put("components/ui-component/templates/chart.html",'<md-card ui-card-size="{{ me.item.width }}x{{ me.item.height }}" layout-align="center center" ng-class="[{\'nr-dashboard-disabled\':me.item.disabled}, me.item.className]" node-id="{{me.item.id}}"> <div class="nr-dashboard-chart-container" style="width:100%; height:100%;"> <p class="label nr-dashboard-chart-title" ng-class="{\'nr-dashboard-chart-titlel\':(me.item.width > 3)}" ng-bind-html="me.item.getLabel()"> </p> <ui-chart-js class="nr-dashboard-chart" ng-class="{\'nr-dashboard-chart-nolabel\':me.item.getLabel() == \'\'}" ng-swipe-right="$event.stopPropagation();" ng-swipe-left="$event.stopPropagation();"> </ui-chart-js> <p class="blank-label" ng-if="config && config.nodata">{{ me.item.nodata }} </p> </div> </md-card> '),e.put("components/ui-component/templates/colour-picker.html",'<md-card ui-card-size="{{ me.item.width }}x{{ me.item.height }}" flex layout="row" layout-align="space-between center" class="nr-dashboard-colour-picker" ng-class="[{\'nr-dashboard-disabled\':me.item.disabled}, me.item.className]" node-id="{{me.item.id}}"> <p> <span ng-hide="(me.item.width < 2) || (me.item.width < 5 && (me.item.inline || me.item.textValue))" class="label" ng-bind-html="me.item.getLabel()"> </span> </p> <color-picker ng-model="me.item.value" aria-label="{{me.item.label}}" ng-attr-options="me.item.options" ng-attr-event-api="me.item.eventapi" ng-keypress="me.item.key($event)" ng-swipe-right="$event.stopPropagation();" ng-swipe-left="$event.stopPropagation();"> </color-picker> </md-card> '),e.put("components/ui-component/templates/date-picker.html",'<md-card ui-card-size="{{ me.item.width }}x{{ me.item.height }}" flex layout="row" layout-align="space-between center" class="nr-dashboard-date-picker" ng-class="[{\'nr-dashboard-disabled\':me.item.disabled}, me.item.className]" node-id="{{me.item.id}}"> <md-input-container flex layout="row"> <p class="nr-dashboard-date-picker-label" ng-if="me.item.label" ng-bind-html="me.item.getLabel()"> </p> <md-datepicker class="nr-dashboard-date-picker" md-placeholder="{{me.item.getLabel()}}" md-open-on-focus ng-model="me.item.ddd" ng-blur="me.setDate()"> </md-datepicker> </md-input-container> </md-card> '),e.put("components/ui-component/templates/dropdown.html",'<md-card ui-card-size="{{ me.item.width }}x{{ me.item.height }}" layout="row" layout-align="space-between center" class="nr-dashboard-dropdown" ng-class="[{\'nr-dashboard-disabled\':me.item.disabled}, me.item.className]" node-id="{{me.item.id}}"> <md-input-container flex layout="row"> <p ng-if="me.item.width>1 && me.item.getLabel().length>0" class="label" ng-if="me.item.label" ng-bind-html="me.item.getLabel()"> </p> <md-tooltip ng-if="me.item.getTooltip().length" md-delay="700" md-direction="bottom" ng-bind-html="me.item.getTooltip()"> </md-tooltip> <md-select ng-if="!me.item.multiple" ng-change="me.itemChanged()" ng-disabled="me.item.disabled" ng-model="me.item.value" placeholder="{{ me.item.place }}" flex="100"> <md-select-header ng-if="me.item.options.length > 7" class="nr-dashboard-dropdown-header"> <md-input-container class="md-block" style="height:32px;" flex> <input ng-model="me.searchTerm" ng-keydown="$event.stopPropagation();" ng-click="$event.stopPropagation();" type="search" aria-label="Filter"> <ng-md-icon icon="search"></ng-md-icon> </md-input-container> </md-select-header> <md-option ng-value="opt.value" ng-repeat="opt in me.item.options | filter: { label: me.searchTerm }">{{ opt.label }} </md-option> </md-select> <md-select ng-if="me.item.multiple" ng-change="me.itemChanged()" ng-disabled="me.item.disabled" md-on-close="me.closed()" multiple="multiple" ng-model="me.item.value" placeholder="{{ me.item.place }}" flex="100"> <md-select-header ng-if="me.item.options.length > 7" class="nr-dashboard-dropdown-header"> <md-checkbox md-no-ink aria-label="Select all" ng-model="me.selectAll" ng-change="me.checkAll()" style="width:unset;"></md-checkbox> <md-input-container class="md-block" style="height:32px;" flex> <input ng-model="me.searchTerm" ng-keydown="$event.stopPropagation()" type="search" aria-label="Filter"> <ng-md-icon icon="search"></ng-md-icon> </md-input-container> </md-select-header> <md-option ng-value="opt.value" ng-repeat="opt in me.item.options | filter: { label: me.searchTerm }">{{ opt.label }} </md-option> </md-select> </md-input-container> </md-card> '),e.put("components/ui-component/templates/form.html",'<md-card ui-card-size="{{me.item.width}}x{{(me.item.height > me.item.rowCount ? me.item.height : me.item.rowCount )}}" layout="row" layout-align="space-between center" class="nr-dashboard-form" ng-class="[{\'nr-dashboard-disabled\':me.item.disabled}, me.item.className]" node-id="{{me.item.id}}"> <form name="form" ng-submit="me.submit(form)" style="margin-top:{{(me.item.label ? 0 : me.item.rowCount < 3 ? me.item.rowHeight/6 : me.item.rowHeight/2.5)}}px"> <p class="formlabel" style="margin-bottom:{{(me.item.rowHeight/9)}}px" ng-if="me.item.label" ng-bind-html="me.item.getLabel()"></p> <div class="formElement" ng-class="{\'formElementSplit\':(me.item.splitLayout)}" layout-gt-sm="row" ng-repeat="opt in me.item.options track by $index"> <md-input-container class="md-block" style="height:{{(me.item.rowHeight * (opt.type==\'multiline\' ? opt.rows : 1)) }}px" flex> <label ng-if="(opt.type==\'text\' || opt.type==\'number\' || opt.type==\'email\' || opt.type==\'multiline\' || opt.type==\'password\' || opt.type==\'date\' || opt.type==\'time\') && opt.label">{{opt.label}}</label> <input ng-if="opt.type==\'text\' || opt.type==\'email\' || opt.type==\'password\'" type="{{opt.type}}" ng-model="me.item.formValue[opt.value]" ng-required="opt.required" ng-keydown="me.stop($event)"> <input ng-if="opt.type==\'date\'" type="{{opt.type}}" ng-model="me.item.formValue[opt.value]" ng-required="opt.required" ng-keydown="me.stop($event)" placeholder="yyyy-mm-dd"> <input ng-if="opt.type==\'time\'" type="{{opt.type}}" ng-model="me.item.formValue[opt.value]" ng-required="opt.required" ng-keydown="me.stop($event)" placeholder="HH:MM"> <input ng-if="opt.type==\'number\'" type="{{opt.type}}" ng-model="me.item.formValue[opt.value]" ng-required="opt.required" ng-keydown="me.stop($event)" step="any"> <textarea ng-if="opt.type==\'multiline\'" md-no-autogrow ng-required="opt.required" ng-model="me.item.formValue[opt.value]" style="height:{{(opt.rows * me.item.sy) - 10}}px; padding:10px 2px 1px 0;"></textarea> <md-switch ng-if="opt.type==\'switch\'" md-no-ink ng-model="me.item.formValue[opt.value]">{{opt.label}}</md-switch> <md-checkbox ng-if="opt.type==\'checkbox\'" md-no-ink aria-label="Checkbox No Ink" ng-model="me.item.formValue[opt.value]"> {{opt.label}}</md-checkbox> </md-input-container> \x3c!-- <md-datepicker ng-if="opt.type==\'date\'" ng-model="me.item.formValue[opt.value]"></md-datepicker> --\x3e </div> <div class="form-control" ng-class="{\'form-control-single\':me.item.cancel == \'\',\'form-control-no-label\':me.item.label == \'\'}" style="margin-top:{{( me.item.label ==\'\' ? me.item.rowCount < 3 ? me.item.rowHeight * 0.4 : me.item.rowHeight * 0.2 : me.item.rowHeight * -0.1)}}px;"> <md-button class="md-raised nr-dashboard-form-button" type="submit" style="height:{{(me.item.sy -4)}}px;line-height:{{(me.item.sy -4)}}px">{{me.item.submit}}</md-button> <md-button ng-if="me.item.cancel != \'\'" class="md-raised nr-dashboard-form-button" style="height:{{(me.item.sy -4)}}px;line-height:{{(me.item.sy -4)}}px" ng-click="me.reset()">{{me.item.cancel}}</md-button> </div> </form> </md-card> cancel'),e.put("components/ui-component/templates/gauge.html",'<md-card ui-card-size="{{ me.item.width }}x{{ me.item.height }}" layout-align="center center" ng-class="[{\'nr-dashboard-disabled\':me.item.disabled}, me.item.className]" node-id="{{me.item.id}}"> <p class="label nr-dashboard-gauge-title" ng-class="{\'nr-dashboard-gauge-titlel\':(me.item.width > 3)}" ng-bind-html="me.item.getLabel()" ng-hide="(me.item.height <= 2)"> </p> <p ng-show="(me.item.height == 2)" ng-bind-html="me.item.getLabel()" ng-class="{\'nr-dashboard-gauge-titlem\':(me.item.height == 2)}"> </p> <p ng-show="(me.item.height == 1)" ng-bind-html="me.item.getLabel()" ng-class="{\'nr-dashboard-gauge-titles\':(me.item.height == 1)}"> </p> <ui-gauge style="text-align:center;" class="nr-dashboard-gauge"> </ui-gauge> </md-card> '),e.put("components/ui-component/templates/numeric.html",'<md-card ui-card-size="{{ me.item.width }}x{{ me.item.height }}" flex layout="row" layout-align="space-between center" class="nr-dashboard-numeric" ng-class="[{\'nr-dashboard-disabled\':me.item.disabled}, me.item.className]" node-id="{{me.item.id}}"> <p class="label" ng-bind-html="me.item.getLabel()"> </p> <md-tooltip ng-if="me.item.getTooltip().length" md-delay="700" md-direction="bottom" ng-bind-html="me.item.getTooltip()"> </md-tooltip> <div layout="row" layout-align="center center"> <md-button class="md-icon-button down-button" aria-label="{{me.item.label}}" ng-mousedown="me.periodicChange(-me.item.step)" ng-mouseup="me.stopPeriodic()" ng-mouseleave="me.stopPeriodic()" style="z-index:1"> <ui-icon icon="expand_more"></ui-icon> </md-button> <center> <p ng-if="(me.item.ed === false)" class="value" style="min-width:{{me.item.minWidth}}px;" ng-bind-html="me.item.getText()"> </p> <span ng-if="(me.item.ed === true)"> <span class="value" ng-bind-html="me.item.pre"></span> <input ng-model="me.item.value" ng-change="me.newValue()" class="value" ng-disabled="me.item.disabled" style="max-width:{{me.item.minWidth}}px;"> <span class="value" ng-bind-html="me.item.post"></span> </span> </center> <md-button class="md-icon-button up-button" aria-label="{{me.item.label}}" ng-mousedown="me.periodicChange(me.item.step)" ng-mouseup="me.stopPeriodic()" ng-mouseleave="me.stopPeriodic()" style="z-index:1"> <ui-icon icon="expand_less"></ui-icon> </md-button> </div> </md-card> '),e.put("components/ui-component/templates/slider.html",'<md-card ui-card-size="{{ me.item.width }}x{{ me.item.height }}" flex layout="row" layout-align="space-between center" class="nr-dashboard-slider" ng-class="[{\'nr-dashboard-disabled\':me.item.disabled}, {\'nr-dashboard-slider-v\':(me.item.width < me.item.height)}, me.item.className]" ng-swipe-right="$event.stopPropagation();" ng-swipe-left="$event.stopPropagation();" node-id="{{me.item.id}}"> <p ng-show="{{me.item.width >= me.item.height}}" class="label" ng-bind-html="me.item.getLabel()"> </p> <md-tooltip ng-if="me.item.getTooltip().length" md-delay="700" md-direction="bottom" ng-bind-html="me.item.getTooltip()"> </md-tooltip> <md-slider ng-if="me.item.outs===\'all\'" flex="100" min="{{me.item.min}}" max="{{me.item.max}}" step="{{me.item.step}}" ng-model="me.item.value" aria-label="{{me.item.label}}" ng-change="me.valueChanged(10)" ng-on-wheel="me.wheel($event)" style="z-index:1; touch-action:none; min-width:32px;" ng-attr-md-vertical="{{ (me.item.width < me.item.height) || undefined}}" ng-attr-md-invert="{{ me.item.invert || undefined}}"> </md-slider> <md-slider ng-if="me.item.outs===\'end\'" md-discrete flex="100" min="{{me.item.min}}" max="{{me.item.max}}" step="{{me.item.step}}" ng-model="me.item.value" aria-label="{{me.item.label}}" ng-change="me.mchange()" ng-mouseup="me.mup()" ng-mouseleave="me.mleave()" ng-mouseenter="me.menter()" style="z-index:1; touch-action:none; min-width:32px;" ng-style="(me.item.width >= me.item.height) && {\'margin-top\':\'20px\'};" ng-attr-md-vertical="{{ (me.item.width < me.item.height) || undefined}}" ng-attr-md-invert="{{ me.item.invert || undefined}}"> </md-slider> <p ng-hide="{{me.item.width >= me.item.height}}" class="label-v" ng-bind-html="me.item.getLabel()"> </p> </md-card> '),e.put("components/ui-component/templates/spacer.html",'<md-card ui-card-size="{{ me.item.width }}x{{ me.item.height }}" layout="{{ me.item.layout }}" layout-align="{{ me.item.layoutAlign }}" class="nr-dashboard-spacer" ng-class="[{\'nr-dashboard-disabled\':me.item.disabled}, me.item.className]"> </md-card> '),e.put("components/ui-component/templates/switch.html",'<md-card ui-card-size="{{ me.item.width }}x{{ me.item.height }}" layout="row" layout-align="space-between center" class="nr-dashboard-switch" ng-click="me.switchClick()" ng-class="[{\'nr-dashboard-disabled\':me.item.disabled}, me.item.className]" node-id="{{me.item.id}}"> <p ng-if="me.item.label && (me.item.width !== 1)" class="label" ng-bind-html="me.item.getLabel()"> </p> <md-tooltip ng-if="me.item.getTooltip().length" md-delay="700" md-direction="bottom" ng-bind-html="me.item.getTooltip()"> </md-tooltip> <md-switch ng-model="me.item.value" ng-change="me.item.value = !me.item.value" ng-swipe-right="$event.stopPropagation();" ng-swipe-left="$event.stopPropagation();" aria-label="{{me.item.label}}" ng-class="{\'center\' : !me.item.label}" ng-if="!me.item.oncolor || !me.item.onicon || !me.item.offcolor || !me.item.officon" style="z-index:1"> </md-switch> <ui-icon icon="{{me.item.onicon}}" ng-style="{color: me.item.oncolor}" ng-class="{\'center\' : !me.item.label, \'ng-hide\': !me.item.value}" class="{{me.item.animate}}" ng-if="me.item.oncolor && me.item.onicon && me.item.offcolor && me.item.officon" style="z-index:1"> </ui-icon> <ui-icon icon="{{me.item.officon}}" ng-style="{color:me.item.offcolor}" ng-class="{\'center\' : !me.item.label, \'ng-hide\': me.item.value}" class="{{me.item.animate}}" ng-if="me.item.oncolor && me.item.onicon && me.item.offcolor && me.item.officon" style="z-index:1"> </ui-icon> </md-card> '),e.put("components/ui-component/templates/template.html",'<md-card ui-template="me.item.format" ui-card-size="{{ me.item.width }}x{{ me.item.height }}" class="nr-dashboard-template {{ me.item.class }}" ng-class="[{\'nr-dashboard-disabled\':me.item.disabled}, me.item.className]" ng-show="{{me.item.height >= 0}}" node-id="{{me.item.id}}"> </md-card> '),e.put("components/ui-component/templates/text-input-CR.html",'<md-card ui-card-size="{{ me.item.width }}x{{ me.item.height }}" layout="row" layout-align="space-between center" class="nr-dashboard-textinput" ng-class="[{\'nr-dashboard-disabled\':me.item.disabled}, me.item.className]" node-id="{{me.item.id}}"> <md-input-container class="md-block" flex md-is-error="false" ng-class="{\'has-label\':me.item.label}"> <label ng-bind-html="me.item.getLabel()"></label> <md-tooltip ng-if="me.item.getTooltip().length" md-delay="700" md-direction="bottom" ng-bind-html="me.item.getTooltip()"> </md-tooltip> <input ng-model="me.item.value" ng-model-options="{\'timezone\':\'UTC\'}" ng-keydown="me.keyPressed($event)" ng-blur="me.item.sendOnBlur ? me.keyPressed($event) : false" ng-trim="false" ng-disabled="me.item.disabled" aria-label="{{me.item.label}}" type="{{me.item.mode}}" style="z-index:1" step="any"> </md-input-container> </md-card> '),e.put("components/ui-component/templates/text-input.html",'<md-card ui-card-size="{{ me.item.width }}x{{ me.item.height }}" layout="row" layout-align="space-between center" class="nr-dashboard-textinput" ng-class="[{\'nr-dashboard-disabled\':me.item.disabled}, me.item.className]" node-id="{{me.item.id}}"> <md-input-container class="md-block" flex md-is-error="false" ng-class="{\'has-label\':me.item.label}"> <label ng-bind-html="me.item.getLabel()"></label> <md-tooltip ng-if="me.item.getTooltip().length" md-delay="700" md-direction="bottom" ng-bind-html="me.item.getTooltip()"> </md-tooltip> <input ng-model="me.item.value" ng-model-options="{\'timezone\':\'UTC\'}" ng-change="me.valueChanged({{me.item.delay}})" ng-trim="false" ng-disabled="me.item.disabled" aria-label="{{me.item.label}}" type="{{me.item.mode}}" style="z-index:1" ng-style="(me.item.mode===\'color\') && {\'padding-left\':\'25%\'}" step="any"> </md-input-container> </md-card> '),e.put("components/ui-component/templates/text.html",'<md-card ui-card-size="{{ me.item.width }}x{{ me.item.height }}" layout="{{ me.item.layout }}" layout-align="{{ me.item.layoutAlign }}" class="nr-dashboard-text" ng-class="[ me.item.safeLabel, {\'nr-dashboard-disabled\':me.item.disabled}, me.item.className]" node-id="{{me.item.id}}"> <p class="label" ng-bind-html="me.item.getLabel()"></p> <p class="value" ng-bind-html="me.item.getText()"></p> </md-card> ')}]);
    "version": "3.1.9",
                if (me.item.format.indexOf("constructor") === -1) {
                    me.item.getText = $interpolate(me.item.format).bind(null, me.item);
                }
                else {
                    me.item.getText = function() { return me.item.format };
                }
                if (me.item.label.indexOf("constructor") === -1) {
                    me.item.getLabel = $interpolate(me.item.label).bind(null, me.item);
                    me.item.safeLabel = "nr-dashboard-widget-" + (me.item.label).replace(/\W/g,'_');
                }
                else {
                    me.item.getText = function() { return me.item.label };
                }
                if (me.item.tooltip.indexOf("constructor") === -1) {
                    me.item.getTooltip = $interpolate(me.item.tooltip).bind(null, me.item);
                }
                else {
                    me.item.getText = function() { return me.item.tooltip };
                }
                if (me.item.color.indexOf("constructor") === -1) {
                    me.item.getColor = $interpolate(me.item.color).bind(null, me.item);
                }
                else {
                    me.item.getText = function() { return me.item.color };
                }
                if (me.item.icon.indexOf("constructor") === -1) {
                    me.item.getIcon = $interpolate(me.item.icon).bind(null, me.item);
                }
                else {
                    me.item.getText = function() { return me.item.icon };
                }
                if (me.item.units.indexOf("constructor") === -1) {
                    me.item.getUnits = $interpolate(me.item.units).bind(null, me.item);
                }
                else {
                    me.item.getText = function() { return me.item.units };
                }